diff options
-rw-r--r-- | src/hir/hir.cpp | 15 | ||||
-rw-r--r-- | src/hir/type.cpp | 7 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 9 |
3 files changed, 24 insertions, 7 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 8f35ba0c..c2ad4d00 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -73,14 +73,21 @@ namespace { } throw ""; } - if( right.m_data.is_Generic() ) { - return left.m_data.is_Generic(); - } + // A local generic could match anything, leave that up to the caller if( left.m_data.is_Generic() ) { - // True? (TODO: Check bounds?) return true; } + // A local UfcsKnown can only be becuase it couldn't be expanded earlier, assume it could match + if( left.m_data.is_Path() && left.m_data.as_Path().path.m_data.is_UfcsKnown() ) { + // True? + return true; + } + + // If the RHS (provided) is generic, it can only match if it binds to a local type parameter + if( right.m_data.is_Generic() ) { + return left.m_data.is_Generic(); + } if( left.m_data.tag() != right.m_data.tag() ) { return false; diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 4c7a162f..de60dcb1 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -524,7 +524,14 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x break; } ) + if( v.m_data.tag() != x.m_data.tag() ) { + // HACK: If the path is Opaque, return a fuzzy match. + // - This works around an impl selection bug. + if( v.m_data.is_Path() && v.m_data.as_Path().binding.is_Opaque() ) { + DEBUG("- Fuzzy match due to opaque"); + return Compare::Fuzzy; + } DEBUG("- Tag mismatch " << v << " and " << x); return Compare::Unequal; } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index b44420fb..64a12801 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1880,7 +1880,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ) const { TRACE_FUNCTION_F(trait << FMT_CB(ss, if(params_ptr) { ss << *params_ptr; } else { ss << "<?>"; }) << " for " << type); - // TODO: Parameter defaults - apply here or in the caller? + return this->m_crate.find_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(), [&](const auto& impl) { DEBUG("[find_trait_impls_crate] Found impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type << " " << impl.m_params.fmt_bounds()); @@ -1899,6 +1899,8 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, return impl_params[idx]->compare_with_placeholders(sp, ty, this->m_ivars.callback_resolve_infer()); } }; + // NOTE: If this type references an associated type, the match will incorrectly fail. + // - HACK: match_test_generics_fuzz has been changed to return Fuzzy if there's a tag mismatch and the LHS is an Opaque path match &= impl.m_type.match_test_generics_fuzz(sp, type , this->m_ivars.callback_resolve_infer(), cb); if( params_ptr ) { @@ -1907,14 +1909,14 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, for(unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++) match &= impl.m_trait_args.m_types[i].match_test_generics_fuzz(sp, params.m_types[i], this->m_ivars.callback_resolve_infer(), cb); if( match == ::HIR::Compare::Unequal ) { - DEBUG("- Failed to match parameters - " << impl.m_trait_args << "+" << impl.m_type << " != " << params << "+" << type); + DEBUG("[find_trait_impls_crate] - Failed to match parameters - " << impl.m_trait_args << "+" << impl.m_type << " != " << params << "+" << type); return false; } } else { if( match == ::HIR::Compare::Unequal ) { - DEBUG("- Failed to match type - " << impl.m_type << " != " << type); + DEBUG("[find_trait_impls_crate] - Failed to match type - " << impl.m_type << " != " << type); return false; } } @@ -1972,6 +1974,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, }; auto ty_mono = monomorphise_type_with(sp, impl.m_type, monomorph, false); auto args_mono = monomorphise_path_params_with(sp, impl.m_trait_args, monomorph, false); + // TODO: Expand associated types in these then ensure that they still match the desired types. // Check bounds for this impl // - If a bound fails, then this can't be a valid impl |