From 2fdc5c8f985c8b32fbf618f7b33f4e5a0474f7fe Mon Sep 17 00:00:00 2001 From: Alexander McCord Date: Sun, 26 May 2024 22:17:28 -0700 Subject: [PATCH] Add ADL-based hash resolution. --- EqSat/include/Luau/Language.h | 69 +++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/EqSat/include/Luau/Language.h b/EqSat/include/Luau/Language.h index 73dd089a..edbed9af 100644 --- a/EqSat/include/Luau/Language.h +++ b/EqSat/include/Luau/Language.h @@ -11,6 +11,26 @@ namespace Luau::EqSat { +template +struct LanguageHash +{ + size_t operator()(const T&) const + { + // See available specializations at the bottom of this file. + static_assert(false, "missing languageHash specialization"); + } +}; + +template +std::size_t languageHash(const T& lang) { + return LanguageHash{}(lang); +} + +inline size_t hashCombine(size_t& seed, size_t hash) +{ + return seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); +} + #define LUAU_EQSAT_ATOM(name, t) \ struct name : public ::Luau::EqSat::Atom \ { \ @@ -46,20 +66,22 @@ namespace Luau::EqSat return !(*this == rhs); \ } +#define DERIVE_HASH(name, field) \ + struct Hash \ + { \ + size_t operator()(const name& value) const \ + { \ + return languageHash(value.field); \ + } \ + } + template struct Atom { T value; DERIVE_EQ(Atom, value); - - struct Hash - { - size_t operator()(const Atom& atom) const - { - return std::hash{}(atom.value); - } - }; + DERIVE_HASH(Atom, value); }; /// Empty base class just for static_asserts. @@ -111,17 +133,11 @@ public: } DERIVE_EQ(Node, array); - - struct Hash - { - size_t operator()(const Node& node) const - { - return 0; - } - }; + DERIVE_HASH(Node, array); }; #undef DERIVE_EQ +#undef DERIVE_HASH // `Language` is very similar to `Luau::Variant` with enough differences warranting a different type altogether. // @@ -270,4 +286,25 @@ public: }; }; +template +struct LanguageHash{}(std::declval()))>> +{ + size_t operator()(const T& t) const + { + return std::hash{}(t); + } +}; + +template +struct LanguageHash> +{ + size_t operator()(const std::array& array) const + { + size_t seed = 0; + for (Id id : array) + hashCombine(seed, languageHash(id)); + return seed; + } +}; + } // namespace Luau::EqSat