From 4c545f182c8304f3001495cc0cf319cb5e5489c3 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Mon, 4 May 2020 01:21:07 +0200 Subject: [PATCH] Fix issue with some std::unordered_map implementations We currently don't adhere to the restriction that if two items are equal to each other, their hashes must be the same too. This comes from the issue that unitless numbers compare equal to the same number even if they have units. --- src/ast.hpp | 6 +++--- src/ast_helpers.hpp | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/ast.hpp b/src/ast.hpp index c3b1e3ba9c..e7dcaf657d 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -358,7 +358,7 @@ namespace Sass { class Hashed { private: std::unordered_map< - K, T, ObjHash, ObjEquality + K, T, ObjHash, ObjHashEquality > elements_; sass::vector _keys; @@ -396,7 +396,7 @@ namespace Sass { bool has_duplicate_key() const { return duplicate_key_ != nullptr; } K get_duplicate_key() const { return duplicate_key_; } const std::unordered_map< - K, T, ObjHash, ObjEquality + K, T, ObjHash, ObjHashEquality >& elements() { return elements_; } Hashed& operator<<(std::pair p) { @@ -432,7 +432,7 @@ namespace Sass { return *this; } const std::unordered_map< - K, T, ObjHash, ObjEquality + K, T, ObjHash, ObjHashEquality >& pairs() const { return elements_; } const sass::vector& keys() const { return _keys; } diff --git a/src/ast_helpers.hpp b/src/ast_helpers.hpp index b4c4522d39..fa7ae942a5 100644 --- a/src/ast_helpers.hpp +++ b/src/ast_helpers.hpp @@ -149,6 +149,30 @@ namespace Sass { } }; + // ########################################################################### + // Special compare function only for hashes. + // We need to make sure to not have objects equal that + // have different hashes. This is currently an issue, + // since `1px` is equal to `1` but have different hashes. + // This goes away once we remove unitless equality. + // ########################################################################### + + template + // Compare the objects and its hashes + bool ObjHashEqualityFn(const T& lhs, const T& rhs) { + if (lhs == nullptr) return rhs == nullptr; + else if (rhs == nullptr) return false; + else return lhs->hash() == rhs->hash(); + } + struct ObjHashEquality { + template + // Compare the objects and its contents and hashes + bool operator() (const T& lhs, const T& rhs) const { + return ObjEqualityFn(lhs, rhs) && + ObjHashEqualityFn(lhs, rhs); + } + }; + // ########################################################################### // Implement ordering operations for AST Nodes // ###########################################################################