diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-10 14:35:51 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-10 14:35:51 +0800 |
commit | 45082a3c953c6acfce103cdc4e0bd4ed8c3b46f0 (patch) | |
tree | 3b10347eb51868bbbc6cd8fa622518df52cec8d7 | |
parent | ec93160044546d12bceaa95c8a5b0d6d7dd534ee (diff) | |
download | mrust-45082a3c953c6acfce103cdc4e0bd4ed8c3b46f0.tar.gz |
HIR Typecheck - Recursively expand associated types
-rw-r--r-- | src/hir_typeck/expr.cpp | 7 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 8 |
2 files changed, 9 insertions, 6 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 4a1a729f..9afe07fc 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1490,10 +1490,11 @@ namespace typeck { TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e), (Infer, auto new_ty = this->context.get_type(ty).clone(); - if( new_ty.m_data.is_Infer() ) { - ERROR(sp, E0000, "Failed to infer type " << new_ty << " in " << top_type); - } + // - Move over before checking, so that the source type mentions the correct ivar ty = mv$(new_ty); + if( ty.m_data.is_Infer() ) { + ERROR(sp, E0000, "Failed to infer type " << ty << " in " << top_type); + } check_type_resolved(sp, ty, top_type); ), (Diverge, diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index efcf3549..5a6ec5ad 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -644,7 +644,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR assert( ! left.m_data.is_Infer() || left.m_data.as_Infer().index != ~0u ); assert( !right.m_data.is_Infer() || right.m_data.as_Infer().index != ~0u ); // - Convert left/right types into resolved versions (either root ivar, or generic replacement) - const auto& l_t1 = left.m_data.is_Generic() ? cb_left (left ) : this->get_type(left ); + const auto& l_t1 = left .m_data.is_Generic() ? cb_left (left ) : this->get_type(left ); const auto& r_t1 = right.m_data.is_Generic() ? cb_right(right) : this->get_type(right); if( l_t1 == r_t1 ) { return ; @@ -654,6 +654,9 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR const auto& l_t = this->expand_associated_types_to(sp, l_t1, left_tmp); ::HIR::TypeRef right_tmp; const auto& r_t = this->expand_associated_types_to(sp, r_t1, right_tmp); + if( l_t == r_t ) { + return ; + } DEBUG("- l_t = " << l_t << ", r_t = " << r_t); TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Infer, r_e, @@ -987,7 +990,6 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, ), (UfcsKnown, DEBUG("Locating associated type for " << e.path); - // TODO: Use the marker `e.binding` to tell if it's worth trying *e2.type = expand_associated_types(sp, mv$(*e2.type)); @@ -1150,7 +1152,7 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, return *impl_args[ge.binding]; }); DEBUG("Converted UfcsKnown - " << e.path << " = " << new_type << " using " << e2.item << " = " << impl_ptr->m_types.at( e2.item )); - return new_type; + return expand_associated_types(sp, mv$(new_type)); } // TODO: If there are no ivars in this path, set its binding to Opaque |