diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-16 22:04:11 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-16 22:04:11 +0800 |
commit | ee147e0b52f8ff12e69c218f46b6833360db6b02 (patch) | |
tree | 402bc9419da18eb938c49266f383faac6b23c010 | |
parent | 316e3f1c22663c17b2659762beb9d438787cdd12 (diff) | |
download | mrust-ee147e0b52f8ff12e69c218f46b6833360db6b02.tar.gz |
HIR Typcheck Expr - Prune `coerce_from` list down to bottom type
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 34 |
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; |