diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-10 16:54:27 +1000 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-10 16:54:27 +1000 |
commit | 0fa60c33115aea3efebd788d2eb981862971cc52 (patch) | |
tree | c22b288e933c4b5e41ecaf36ffbf499797f7e010 /src | |
parent | 87e8becbb724486004b5b4d2711a80eb3a1b199e (diff) | |
download | mrust-0fa60c33115aea3efebd788d2eb981862971cc52.tar.gz |
HIR Typecheck CS - Allow fuzzy matches when checking impl bounds
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/helpers.cpp | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 69998bca..2743d58f 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1693,7 +1693,8 @@ 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: Check bounds + // Check bounds for this impl + // - If a bound fails, then this can't be a valid impl for(const auto& bound : impl.m_params.m_bounds) { TU_MATCH(::HIR::GenericBound, (bound), (be), @@ -1711,30 +1712,39 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, DEBUG("- " << real_type << " : " << real_trait); auto rv = this->find_trait_impls(sp, real_trait.m_path.m_path, real_trait.m_path.m_params, real_type, [&](const auto&, const auto& a, const auto& t) { for(const auto& assoc_bound : real_trait.m_type_bounds) { + ::HIR::TypeRef tmp; + const ::HIR::TypeRef* ty_p; + auto it = t.find(assoc_bound.first); if( it == t.end() ) { - auto ty = ::HIR::TypeRef(::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { box$(real_type.clone()), real_trait.m_path.clone(), assoc_bound.first, {} })); - auto ty2 = this->expand_associated_types(sp, mv$(ty)); - - if( ty2 == assoc_bound.second ) { - return true; - } - this->m_ivars.dump(); - TODO(sp, "Check type bound (fuzz) " << ty2 << " = " << assoc_bound.second); + // This bound isn't from this particular trait, go the slow way of using expand_associated_types + tmp = this->expand_associated_types(sp, ::HIR::TypeRef( + ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { box$(real_type.clone()), real_trait.m_path.clone(), assoc_bound.first, {} })) + ); + ty_p = &tmp; } else { - if( this->m_ivars.get_type(it->second) == assoc_bound.second ) { - return true; - } - this->m_ivars.dump(); - TODO(sp, "Check type bound (fuzz) " << it->second << " = " << assoc_bound.second); + ty_p = &this->m_ivars.get_type(it->second); + } + const auto& ty = *ty_p; + auto cmp = ty.compare_with_placeholders(sp, assoc_bound.second, this->m_ivars.callback_resolve_infer()); + switch(cmp) + { + case ::HIR::Compare::Equal: + continue; + case ::HIR::Compare::Unequal: + return false; + case ::HIR::Compare::Fuzzy: + // TODO: When a fuzzy match is encountered on a conditional bound, returning `false` can lead to an false negative (and a compile error) + // BUT, returning `true` could lead to it being selected. (Is this a problem, should a later validation pass check?) + DEBUG("[find_trait_impls_crate] Fuzzy match between " << ty << " and " << assoc_bound.second); + continue ; } } return true; }); if( !rv ) { - // false = keep going return false; } ), |