summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/helpers.cpp2
-rw-r--r--src/hir_typeck/impl_ref.cpp2
-rw-r--r--src/hir_typeck/impl_ref.hpp2
-rw-r--r--src/hir_typeck/outer.cpp4
-rw-r--r--src/hir_typeck/static.cpp33
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({});