summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-04-21 09:08:25 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-04-21 09:08:25 +0800
commitd7543b18d1f5480925d92b590869b8f569d34872 (patch)
tree1c3ba807e41a0e5917bcee9d97f0182ed65b4698
parentf96264846fdc79aa220e46b12afcb25f1d12b135 (diff)
downloadmrust-d7543b18d1f5480925d92b590869b8f569d34872.tar.gz
Typecheck Expressions - Improved trait object coercions
-rw-r--r--src/hir_typeck/expr_cs.cpp112
1 files changed, 42 insertions, 70 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 6ad8032b..78bf45f8 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -5512,18 +5512,28 @@ namespace {
}
else if(const auto* sep = src.m_data.opt_Infer())
{
- if(sep->is_lit() && !dst.m_data.is_TraitObject())
+ if(sep->is_lit())
{
- // Literal to anything other than a trait object must be an equality
- DEBUG("Literal with primitive");
- return CoerceResult::Equality;
+ if( !dst.m_data.is_TraitObject())
+ {
+ // Literal to anything other than a trait object must be an equality
+ DEBUG("Literal with primitive");
+ return CoerceResult::Equality;
+ }
+ else
+ {
+ // Fall through
+ }
}
- if( context_mut )
+ else
{
- context_mut->possible_equate_type_unsize_to(sep->index, dst);
+ if( context_mut )
+ {
+ context_mut->possible_equate_type_unsize_to(sep->index, dst);
+ }
+ DEBUG("Src is ivar (" << src << "), return Unknown");
+ return CoerceResult::Unknown;
}
- DEBUG("Src is ivar (" << src << "), return Unknown");
- return CoerceResult::Unknown;
}
else
{
@@ -5727,79 +5737,35 @@ namespace {
// Check for trait impl
if( trait.m_path != ::HIR::SimplePath() )
{
- ImplRef best_impl;
- unsigned int count = 0;
- bool found = context.m_resolve.find_trait_impls(sp, trait.m_path, trait.m_params, src, [&](auto impl, auto cmp) {
- DEBUG("TraitObject coerce from - cmp="<<cmp<<", " << impl);
- count ++;
- best_impl = mv$(impl);
- return cmp == ::HIR::Compare::Equal;
- });
- if( count == 0 )
+ // Just call equate_types_assoc to add the required bounds.
+ if( context_mut )
{
- // TODO: Get a better idea of when there won't ever be an applicable impl
- if( !context.m_ivars.type_contains_ivars(src) ) {
- ERROR(sp, E0000, "The trait " << dep->m_trait << " is not implemented for " << src);
- }
- DEBUG("No impl, but there may eventaully be one");
- return CoerceResult::Unknown;
- }
- if( !found )
- {
- if(count > 1)
+ for(const auto& tyb : dep->m_trait.m_type_bounds)
{
- DEBUG("Defer as there are multiple applicable impls");
- return CoerceResult::Unknown;
- }
-
- if( best_impl.has_magic_params() ) {
- DEBUG("Defer as there were magic parameters");
- return CoerceResult::Unknown;
+ context_mut->equate_types_assoc(sp, tyb.second, trait.m_path, trait.m_params.clone(), src, tyb.first.c_str(), false);
}
-
- // TODO: Get a better way of equating these that doesn't require getting copies of the impl's types
- if( context_mut )
+ if( dep->m_trait.m_type_bounds.empty() )
{
- context_mut->equate_types(sp, src, best_impl.get_impl_type());
- auto args = best_impl.get_trait_params();
- assert(trait.m_params.m_types.size() == args.m_types.size());
- for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++)
- {
- context_mut->equate_types(sp, trait.m_params.m_types[i], args.m_types[i]);
- }
- for(const auto& tyb : dep->m_trait.m_type_bounds)
- {
- auto ty = best_impl.get_type(tyb.first.c_str());
- if( ty != ::HIR::TypeRef() )
- {
- context_mut->equate_types(sp, tyb.second, ty);
- }
- else
- {
- // Error? Log? ...
- DEBUG("Associated type " << tyb.first << " not present in impl, can't equate");
- }
- }
+ context_mut->add_trait_bound(sp, src, trait.m_path, trait.m_params.clone());
}
}
+ else
+ {
+ // TODO: Should this check?
+ }
}
- for(const auto& marker : dep->m_markers)
+ if( context_mut )
{
- bool found = context.m_resolve.find_trait_impls(sp, marker.m_path, marker.m_params, src, [&](auto impl, auto cmp) {
- DEBUG("TraitObject coerce from - cmp="<<cmp<<", " << impl);
- return cmp == ::HIR::Compare::Equal;
- });
- // TODO: Allow fuzz and equate same as above?
- if( !found )
+ for(const auto& marker : dep->m_markers)
{
- // TODO: Get a better idea of when there won't ever be an applicable impl
- if( !context.m_ivars.type_contains_ivars(src) ) {
- ERROR(sp, E0000, "The trait " << marker << " is not implemented for " << src);
- }
- return CoerceResult::Unknown;
+ context_mut->add_trait_bound(sp, src, marker.m_path, marker.m_params.clone());
}
}
+ else
+ {
+ // TODO: Should this check?
+ }
// Add _Unsize operator
return CoerceResult::Unsize;
@@ -6842,6 +6808,12 @@ namespace {
return false;
}
+ // Don't attempt to guess literalS
+ if( ty_l.m_data.as_Infer().is_lit() )
+ {
+ DEBUG(i << ": Literal " << ty_l);
+ return false;
+ }
if( ! ivar_ent.has_rules() ) {
// No rules, don't do anything (and don't print)
DEBUG(i << ": No rules");
@@ -7811,7 +7783,7 @@ namespace {
context.equate_types(sp, ty_l, *good_types.front());
return true;
}
- else if( good_types.size() > 0 && !honour_disable && good_types.size() > n_good_ints )
+ else if( good_types.size() > 0 && !honour_disable )
{
auto typ_is_borrow = [&](const ::HIR::TypeRef* typ) { return typ->m_data.is_Borrow(); };
// NOTE: We want to select from sets of primitives and generics (which can be interchangable)