summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-16 22:04:11 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-16 22:04:11 +0800
commitee147e0b52f8ff12e69c218f46b6833360db6b02 (patch)
tree402bc9419da18eb938c49266f383faac6b23c010
parent316e3f1c22663c17b2659762beb9d438787cdd12 (diff)
downloadmrust-ee147e0b52f8ff12e69c218f46b6833360db6b02.tar.gz
HIR Typcheck Expr - Prune `coerce_from` list down to bottom type
-rw-r--r--src/hir_typeck/expr_cs.cpp34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 6a66f78b..3496557d 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -5020,6 +5020,19 @@ namespace {
return nullptr;
}
+
+ /// Returns true if `dst` is found when dereferencing `src`
+ static bool type_derefs_from(const Span& sp, const Context& context, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) {
+
+ ::HIR::TypeRef tmp;
+ const ::HIR::TypeRef* ty = &src;
+ do
+ {
+ if( context.m_ivars.types_equal(*ty, dst) )
+ return true;
+ } while( (ty = context.m_resolve.autoderef(sp, *ty, tmp)) );
+ return false;
+ }
};
@@ -5058,7 +5071,7 @@ namespace {
DEBUG("-- " << ty_l << " FROM=Coerce:[" << ivar_ent.types_coerce_from << "] / Unsize:[" << ivar_ent.types_unsize_from << "],"
<< " TO=Coerce:[" << ivar_ent.types_coerce_to << "] / Unsize:[" << ivar_ent.types_unsize_to << "]");
- // TODO: Find an entry in the `types_unsize_from` list that all other entries can unsize to
+ // Find an entry in the `types_unsize_from` list that all other entries can unsize to
H::dedup_type_list_with(ivar_ent.types_unsize_from, [&](const auto& l, const auto& r) {
// &T and T
TU_IFLET( ::HIR::TypeRef::Data, l.m_data, Borrow, le,
@@ -5079,6 +5092,25 @@ namespace {
}
return DedupKeep::Both;
});
+ // Find an entry in the `types_coerce_from` list that all other entries can coerce to
+ H::dedup_type_list_with(ivar_ent.types_coerce_from, [&](const auto& l, const auto& r) {
+ if( l.m_data.is_Infer() || r.m_data.is_Infer() )
+ return DedupKeep::Both;
+
+ if( l.m_data.is_Borrow() )
+ {
+ const auto& le = l.m_data.as_Borrow();
+ const auto& re = r.m_data.as_Borrow();
+
+ // Dereference `*re.inner` until it isn't possible or it equals `*le.inner`
+ // - Repeat going the other direction.
+ if( H::type_derefs_from(sp, context, *le.inner, *re.inner) )
+ return DedupKeep::Left;
+ if( H::type_derefs_from(sp, context, *re.inner, *le.inner) )
+ return DedupKeep::Right;
+ }
+ return DedupKeep::Both;
+ });
// HACK: Merge into a single list.
::std::vector< ::HIR::TypeRef> types_from_o;