diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.hpp | 27 | ||||
-rw-r--r-- | src/hir/path.hpp | 25 | ||||
-rw-r--r-- | src/hir/type.cpp | 88 | ||||
-rw-r--r-- | src/hir/type.hpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 29 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 5 |
6 files changed, 173 insertions, 3 deletions
diff --git a/src/common.hpp b/src/common.hpp index 6dfcd495..7f7dbcb7 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -59,6 +59,15 @@ static inline Ordering ord(unsigned l, unsigned r) else return OrdLess; } +static inline Ordering ord(::std::uintptr_t l, ::std::uintptr_t r) +{ + if(l == r) + return OrdEqual; + else if( l > r ) + return OrdGreater; + else + return OrdLess; +} static inline Ordering ord(const ::std::string& l, const ::std::string& r) { if(l == r) @@ -97,9 +106,25 @@ Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r) i ++; } - + + return OrdEqual; +} +template<typename T, typename U> +Ordering ord(const ::std::map<T,U>& l, const ::std::map<T,U>& r) +{ + auto r_it = r.begin(); + for(const auto& le : l) + { + if( r_it == r.end() ) + return OrdGreater; + auto rv = ::ord( le, *r_it ); + if( rv != OrdEqual ) + return rv; + ++ r_it; + } return OrdEqual; } +#define ORD(a,b) do { Ordering ORD_rv = ::ord(a,b); if( ORD_rv != ::OrdEqual ) return ORD_rv; } while(0) template <typename T> diff --git a/src/hir/path.hpp b/src/hir/path.hpp index 59b5f111..cace3ff9 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -68,6 +68,12 @@ struct SimplePath if( m_components < x.m_components ) return true; return false; } + Ordering ord(const SimplePath& x) const { + auto rv = ::ord(m_crate_name, x.m_crate_name); + if(rv != OrdEqual) return rv; + rv = ::ord(m_components, x.m_components); + return rv; + } friend ::std::ostream& operator<<(::std::ostream& os, const SimplePath& x); }; @@ -84,7 +90,10 @@ struct PathParams PathParams& operator=(PathParams&&) = default; bool operator==(const PathParams& x) const; - //bool operator<(const PathParams& x) const; + bool operator<(const PathParams& x) const { return ord(x) == OrdLess; } + Ordering ord(const PathParams& x) const { + return ::ord(m_types, x.m_types); + } friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x); }; @@ -104,7 +113,13 @@ public: bool operator==(const GenericPath& x) const; bool operator!=(const GenericPath& x) const { return !(*this == x); } - //bool operator<(const GenericPath& x) const; + bool operator<(const GenericPath& x) const { return ord(x) == OrdLess; } + + Ordering ord(const GenericPath& x) const { + auto rv = ::ord(m_path, x.m_path); + if(rv != OrdEqual) return rv; + return ::ord(m_params, x.m_params); + } friend ::std::ostream& operator<<(::std::ostream& os, const GenericPath& x); }; @@ -123,6 +138,12 @@ public: bool operator==(const TraitPath& x) const; bool operator!=(const TraitPath& x) const { return !(*this == x); } + Ordering ord(const TraitPath& x) const { + ORD(m_path, x.m_path); + ORD(m_hrls, x.m_hrls); + return ::ord(m_type_bounds, x.m_type_bounds); + } + friend ::std::ostream& operator<<(::std::ostream& os, const TraitPath& x); }; diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 14fa4c46..7695f066 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -263,6 +263,94 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const ) throw ""; } +Ordering HIR::TypeRef::ord(const ::HIR::TypeRef& x) const +{ + Ordering rv; + + ORD( static_cast<unsigned int>(m_data.tag()), static_cast<unsigned int>(x.m_data.tag()) ); + + TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe), + (Infer, + // TODO: Should comparing inferrence vars be an error? + return ::ord( te.index, xe.index ); + ), + (Diverge, + return OrdEqual; + ), + (Primitive, + return ::ord( static_cast<unsigned>(te), static_cast<unsigned>(xe) ); + ), + (Path, + ORD( (unsigned)te.path.m_data.tag(), (unsigned)xe.path.m_data.tag() ); + TU_MATCH(::HIR::Path::Data, (te.path.m_data, xe.path.m_data), (tpe, xpe), + (Generic, + return ::ord(tpe, xpe); + ), + (UfcsInherent, + ORD(*tpe.type, *xpe.type); + ORD(tpe.item, xpe.item); + return ::ord(tpe.params, xpe.params); + ), + (UfcsKnown, + ORD(*tpe.type, *xpe.type); + ORD(tpe.trait, xpe.trait); + ORD(tpe.item, xpe.item); + return ::ord(tpe.params, xpe.params); + ), + (UfcsUnknown, + ORD(*tpe.type, *xpe.type); + ORD(tpe.item, xpe.item); + return ::ord(tpe.params, xpe.params); + ) + ) + ), + (Generic, + ORD(te.name, xe.name); + if( (rv = ::ord(te.binding, xe.binding)) != OrdEqual ) + return rv; + return OrdEqual; + ), + (TraitObject, + ORD(te.m_trait, xe.m_trait); + ORD(te.m_markers, xe.m_markers); + return OrdEqual; + //return ::ord(te.m_lifetime, xe.m_lifetime); + ), + (Array, + ORD(*te.inner, *xe.inner); + ORD(te.size_val, xe.size_val); + if( te.size_val == ~0u ) + assert(!"TOD: Compre array types with non-resolved sizes"); + return OrdEqual; + ), + (Slice, + return ::ord(*te.inner, *xe.inner); + ), + (Tuple, + return ::ord(te, xe); + ), + (Borrow, + ORD( static_cast<unsigned>(te.type), static_cast<unsigned>(xe.type) ); + return ::ord(*te.inner, *xe.inner); + ), + (Pointer, + ORD( static_cast<unsigned>(te.type), static_cast<unsigned>(xe.type) ); + return ::ord(*te.inner, *xe.inner); + ), + (Function, + ORD(te.is_unsafe, xe.is_unsafe); + ORD(te.m_abi, xe.m_abi); + ORD(te.m_arg_types, xe.m_arg_types); + return ::ord(*te.m_rettype, *xe.m_rettype); + ), + (Closure, + ORD( (::std::uintptr_t)te.node, xe.node); + //assert( te.m_rettype == xe.m_rettype ); + return OrdEqual; + ) + ) + throw ""; +} namespace { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index f75a4d51..c5d08c5f 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -219,6 +219,8 @@ public: bool operator==(const ::HIR::TypeRef& x) const; bool operator!=(const ::HIR::TypeRef& x) const { return !(*this == x); } + bool operator<(const ::HIR::TypeRef& x) const { return ord(x) == OrdLess; } + Ordering ord(const ::HIR::TypeRef& x) const; // Match generics in `this` with types from `x` diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index a66a6f84..fd5533e4 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -940,6 +940,28 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- +void TraitResolution::prep_indexes() +{ + this->iterate_bounds([&](const auto& b) { + TU_MATCH_DEF(::HIR::GenericBound, (b), (be), + ( + ), + (TraitBound, + for( const auto& tb : be.trait.m_type_bounds ) { + DEBUG("Equality (TB) - <" << be.type << " as " << be.trait.m_path << ">::" << tb.first << " = " << tb.second); + auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), be.trait.m_path.clone(), tb.first ) ); + this->m_type_equalities.insert( ::std::make_pair( mv$(ty_l), tb.second.clone() ) ); + } + ), + (TypeEquality, + DEBUG("Equality - " << be.type << " = " << be.other_type); + // TODO: Sort the two types by "complexity" + this->m_type_equalities.insert( ::std::make_pair( be.type.clone(), be.other_type.clone() ) ); + ) + ) + return false; + }); +} // ------------------------------------------------------------------------------------------------------------------- @@ -1095,6 +1117,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- + void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars) { //m_ivars.compact_ivars([&](const ::HIR::TypeRef& t)->auto{ return this->expand_associated_types(Span(), t.clone); }); @@ -1250,6 +1273,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const // - Only try resolving if the binding isn't known if( !e.binding.is_Unbound() ) return input; + // TODO: If opaque, still search a list of known equalities DEBUG("Locating associated type for " << e.path); @@ -1337,6 +1361,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const (TypeEquality, DEBUG("Equality - " << be.type << " = " << be.other_type); if( input == be.type ) { + assume_opaque = false; input = be.other_type.clone(); return true; } @@ -1348,6 +1373,10 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const if( assume_opaque ) { DEBUG("Assuming that " << input << " is an opaque name"); input.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); + + DEBUG("- " << m_type_equalities.size() << " replacements"); + for( const auto& v : m_type_equalities ) + DEBUG(" > " << v.first << " = " << v.second); } input = this->expand_associated_types(sp, mv$(input)); return input; diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index cdcbc12c..2e55978e 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -144,6 +144,8 @@ class TraitResolution const ::HIR::GenericParams* m_impl_params; const ::HIR::GenericParams* m_item_params; + ::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities; + public: TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): m_ivars(ivars), @@ -151,8 +153,11 @@ public: m_impl_params( impl_params ), m_item_params( item_params ) { + prep_indexes(); } + void prep_indexes(); + void compact_ivars(HMTypeInferrence& m_ivars); /// Check if a trait bound applies, using the passed function to expand Generic/Infer types |