summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-19 23:09:32 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-19 23:09:32 +0800
commitec912d7f6237f640c6ab4e4f41bf930b042a1712 (patch)
treee20dcf27df54085062e262b69df7845cb32e0c11 /src
parent75648d51a184fa2936f62fbb82ba399c0b83d7d0 (diff)
downloadmrust-ec912d7f6237f640c6ab4e4f41bf930b042a1712.tar.gz
HIR Typecheck - Fix case where an ivar would refer to itself
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp54
-rw-r--r--src/hir_typeck/helpers.cpp1
2 files changed, 31 insertions, 24 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index f8b3c4cd..2fce29b0 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -1243,7 +1243,6 @@ namespace {
// - If they're not valid, then resolution can be done here.
ASSERT_BUG(sp, !this->context.m_ivars.type_contains_ivars(*e.type), "Found ivar in UfcsInherent");
- #if 1
// - Locate function (and impl block)
const ::HIR::Function* fcn_ptr = nullptr;
const ::HIR::TypeImpl* impl_ptr = nullptr;
@@ -1318,7 +1317,6 @@ namespace {
auto ty = ::HIR::TypeRef(mv$(ft));
this->context.equate_types(node.span(), node.m_res_type, ty);
- #endif
)
)
}
@@ -2229,6 +2227,24 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR
}
#endif
+ // If either side is still a UfcsUnkonw after `expand_associated_types`, then emit an assoc bound instead of damaging ivars
+ TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Path, r_e,
+ TU_IFLET(::HIR::Path::Data, r_e.path.m_data, UfcsKnown, rpe,
+ if( r_e.binding.is_Unbound() ) {
+ this->equate_types_assoc(sp, l_t, rpe.trait.m_path, rpe.trait.m_params.clone().m_types, *rpe.type, rpe.item.c_str());
+ return ;
+ }
+ )
+ )
+ TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Path, l_e,
+ TU_IFLET(::HIR::Path::Data, l_e.path.m_data, UfcsKnown, lpe,
+ if( l_e.binding.is_Unbound() ) {
+ this->equate_types_assoc(sp, r_t, lpe.trait.m_path, lpe.trait.m_params.clone().m_types, *lpe.type, lpe.item.c_str());
+ return ;
+ }
+ )
+ )
+
DEBUG("- l_t = " << l_t << ", r_t = " << r_t);
TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Infer, r_e,
TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Infer, l_e,
@@ -2283,28 +2299,6 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR
}
#endif
- // - If the destructuring would fail
- //if( l_t.compare_with_placeholders(sp, r_t, this->m_ivars.callback_resolve_infer()) == ::HIR::Compare::Unequal )
- //{
- // BUT! It was due to an unknown associated type
- TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Path, r_e,
- TU_IFLET(::HIR::Path::Data, r_e.path.m_data, UfcsKnown, rpe,
- if( r_e.binding.is_Unbound() ) {
- this->equate_types_assoc(sp, l_t, rpe.trait.m_path, rpe.trait.m_params.clone().m_types, *rpe.type, rpe.item.c_str());
- return ;
- }
- )
- )
- TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Path, l_e,
- TU_IFLET(::HIR::Path::Data, l_e.path.m_data, UfcsKnown, lpe,
- if( l_e.binding.is_Unbound() ) {
- this->equate_types_assoc(sp, r_t, lpe.trait.m_path, lpe.trait.m_params.clone().m_types, *lpe.type, lpe.item.c_str());
- return ;
- }
- )
- )
- //}
-
if( l_t.m_data.tag() != r_t.m_data.tag() ) {
ERROR(sp, E0000, "Type mismatch between " << this->m_ivars.fmt_type(l_t) << " and " << this->m_ivars.fmt_type(r_t));
}
@@ -3706,6 +3700,8 @@ namespace {
}
// Types are equal from the view of being coercion targets
+ // - Inequality here means that the targets could coexist (e.g. &[u8; N] and &[u8])
+ // - Equality means that they HAVE to be equal (even if they're not currently due to ivars)
static bool equal_to(const Context& context, const ::HIR::TypeRef& ia, const ::HIR::TypeRef& ib) {
const auto& a = context.m_ivars.get_type(ia);
const auto& b = context.m_ivars.get_type(ib);
@@ -3737,6 +3733,16 @@ namespace {
return context.m_ivars.types_equal(ia2, ib2);
)
)
+ ),
+ (Pointer,
+ if( e_a.type != e_b.type )
+ return false;
+ // TODO: Rules are subtly different when coercing from a pointer?
+ const auto& ia2 = context.m_ivars.get_type(*e_a.inner);
+ const auto& ib2 = context.m_ivars.get_type(*e_b.inner);
+ if(ia2.m_data.is_Infer() || ib2.m_data.is_Infer())
+ return true;
+ return context.m_ivars.types_equal(ia2, ib2);
)
)
//
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 4a15c29e..c7fb4019 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -881,6 +881,7 @@ void HMTypeInferrence::ivar_unify(unsigned int left_slot, unsigned int right_slo
BUG(sp, "Unifying over a concrete type - " << *root_ivar.type);
}
+ DEBUG("IVar " << root_ivar.type->m_data.as_Infer().index << " = @" << left_slot);
root_ivar.alias = left_slot;
root_ivar.type.reset();