diff options
-rw-r--r-- | src/hir_typeck/helpers.cpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/impl_ref.cpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/impl_ref.hpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 4 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 33 |
5 files changed, 31 insertions, 12 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 110ae500..6d382409 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1534,7 +1534,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, } // If the type is specialisable - if( impl.type_is_specializable(pe.item.c_str()) ) { + if( impl.type_is_specialisable(pe.item.c_str()) ) { // Check if this is more specific if( impl.more_specific_than( best_impl ) ) { best_impl = mv$(impl); diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp index 43407f54..4b685b03 100644 --- a/src/hir_typeck/impl_ref.cpp +++ b/src/hir_typeck/impl_ref.cpp @@ -40,7 +40,7 @@ bool ImplRef::more_specific_than(const ImplRef& other) const ) throw ""; } -bool ImplRef::type_is_specializable(const char* name) const +bool ImplRef::type_is_specialisable(const char* name) const { TU_MATCH(Data, (this->m_data), (e), (TraitImpl, diff --git a/src/hir_typeck/impl_ref.hpp b/src/hir_typeck/impl_ref.hpp index 6888b1a9..12d84045 100644 --- a/src/hir_typeck/impl_ref.hpp +++ b/src/hir_typeck/impl_ref.hpp @@ -56,7 +56,7 @@ struct ImplRef ::HIR::TypeRef get_trait_ty_param(unsigned int) const; - bool type_is_specializable(const char* name) const; + bool type_is_specialisable(const char* name) const; ::HIR::TypeRef get_type(const char* name) const; friend ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x); diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 2bcb7228..d5e8e7e9 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -259,13 +259,13 @@ namespace { if( best_impl.more_specific_than(impl) ) return false; best_impl = mv$(impl); - if( ! best_impl.type_is_specializable(pe.item.c_str()) ) + if( ! best_impl.type_is_specialisable(pe.item.c_str()) ) return true; return false; }); if( best_impl.is_valid() ) { // If the type is still specialisable, and there's geerics in the type. - if( best_impl.type_is_specializable(pe.item.c_str()) && pe.type->contains_generics() ) { + if( best_impl.type_is_specialisable(pe.item.c_str()) && pe.type->contains_generics() ) { // Mark it as opaque (because monomorphisation could change things) DEBUG("Still-specialisable impl for " << ty << " also opaque"); e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 7683c2c1..cb01e78d 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -612,26 +612,45 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI ) // 2. Crate-level impls - // TODO: Search for the actual trait containing this associated type + + // - Search for the actual trait containing this associated type ::HIR::GenericPath trait_path; if( !this->trait_contains_type(sp, e2.trait, this->m_crate.get_trait_by_path(sp, e2.trait.m_path), e2.item, trait_path) ) BUG(sp, "Cannot find associated type " << e2.item << " anywhere in trait " << e2.trait); //e2.trait = mv$(trait_path); - rv = this->find_impl(sp, trait_path.m_path, trait_path.m_params, *e2.type, [&](const auto& impl) { + ::ImplRef best_impl; + rv = this->find_impl(sp, trait_path.m_path, trait_path.m_params, *e2.type, [&](auto impl) { DEBUG("[expand_associated_types] Found " << impl); - auto nt = impl.get_type( e2.item.c_str() ); - DEBUG("Converted UfcsKnown - " << e.path << " = " << nt); - input = mv$(nt); - return true; + if( impl.type_is_specialisable(e2.item.c_str()) ) { + if( impl.more_specific_than(best_impl) ) { + best_impl = mv$(impl); + DEBUG("- Still specialisable"); + } + return false; + } + else { + auto nt = impl.get_type( e2.item.c_str() ); + DEBUG("Converted UfcsKnown - " << e.path << " = " << nt); + input = mv$(nt); + return true; + } }); if( rv ) { this->expand_associated_types(sp, input); return; } + if( best_impl.is_valid() ) { + auto nt = best_impl.get_type( e2.item.c_str() ); + DEBUG("Converted UfcsKnown (best specialisation) - " << e.path << " = " << nt); + input = mv$(nt); + + this->expand_associated_types(sp, input); + return; + } - // TODO: If the type is a generic or an opaque associated, we can't know. + // If the type is a generic or an opaque associated, we can't know. // - If the trait contains any of the above, it's unknowable // - Otherwise, it's an error e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); |