diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-07 17:59:55 +1000 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-07 17:59:55 +1000 |
commit | 5ef1f59ce1ba4e0c96206775a72facae0ce744da (patch) | |
tree | c8b07641cb4b69a383c5f5f7d1f89e0ddb03d022 /src | |
parent | dca7fb1c1da918a46fb40e18745e420a16627b8e (diff) | |
download | mrust-5ef1f59ce1ba4e0c96206775a72facae0ce744da.tar.gz |
HIR Typecheck CS - Associated type bounds, hacky handling of deferred type equalities (associated types)
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 72 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 73 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 4 |
3 files changed, 131 insertions, 18 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index eba4eef0..0d9b1344 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -43,7 +43,7 @@ struct Context ::HIR::SimplePath trait; ::HIR::PathParams params; ::HIR::TypeRef impl_ty; - const char* name; // if "", no type is used (and left is ignored) - Just does trait selection + ::std::string name; // if "", no type is used (and left is ignored) - Just does trait selection friend ::std::ostream& operator<<(::std::ostream& os, const Associated& v) { os << v.left_ty << " = " << "<" << v.impl_ty << " as " << v.trait << v.params << ">::" << v.name; @@ -304,7 +304,14 @@ namespace { DEBUG("Bound " << be.type << ": " << be.trait); DEBUG("= (" << real_type << ": " << real_trait << ")"); const auto& trait_params = real_trait.m_params; - context.equate_types_assoc(sp, ::HIR::TypeRef(), be.trait.m_path.m_path, mv$(trait_params.clone().m_types), real_type, ""); + + const auto& trait_path = be.trait.m_path.m_path; + context.equate_types_assoc(sp, ::HIR::TypeRef(), trait_path, mv$(trait_params.clone().m_types), real_type, ""); + + for( const auto& assoc : be.trait.m_type_bounds ) { + auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true); + context.equate_types_assoc(sp, other_ty, trait_path, mv$(trait_params.clone().m_types), real_type, assoc.first.c_str()); + } ), (TypeEquality, auto real_type_left = context.m_resolve.expand_associated_types(sp, monomorphise_type_with(sp, be.type, cache.m_monomorph_cb)); @@ -1612,6 +1619,32 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR return ; ) + // - 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() ) { + // TODO: Try this operation again later? + 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 ; + //TODO(sp, "Defer structural equality of unknown associated type"); + } + ) + ) + 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() ) { + // TODO: Try this operation again later? + 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 ; + //TODO(sp, "Defer structural equality of unknown associated type"); + } + ) + ) + } + 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)); } @@ -2565,20 +2598,20 @@ namespace { DEBUG("- (fail) bounded impl " << v.trait << v.params << " (ty_right = " << context.m_ivars.fmt_type(v.impl_ty)); return false; } + + if( v.name != "" ) { + if( assoc.count(v.name) == 0 ) + BUG(sp, "Getting associated type '" << v.name << "' which isn't in list"); + output_type = assoc.at(v.name).clone(); + } count += 1; if( cmp == ::HIR::Compare::Equal ) { - if( v.name[0] ) { - output_type = assoc.at(v.name).clone(); - } return true; } else { if( possible_impl_ty == ::HIR::TypeRef() ) { possible_impl_ty = impl_ty.clone(); possible_params = args.clone(); - if( v.name[0] ) { - output_type = assoc.at(v.name).clone(); - } } return false; @@ -2586,7 +2619,7 @@ namespace { }); if( found ) { // Fully-known impl - if( v.name[0] ) { + if( v.name != "" ) { context.equate_types(sp, v.left_ty, output_type); } return true; @@ -2603,7 +2636,7 @@ namespace { else if( count == 1 ) { DEBUG("Only one impl " << v.trait << possible_params << " for " << possible_impl_ty << " - params=" << possible_params << ", ty=" << possible_impl_ty << ", out=" << output_type); // Only one possible impl - if( v.name[0] ) { + if( v.name != "" ) { context.equate_types(sp, v.left_ty, output_type); } assert( possible_impl_ty != ::HIR::TypeRef() ); @@ -2665,13 +2698,18 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: } // 3. Check associated type rules DEBUG("--- Associated types"); - for(auto it = context.link_assoc.begin(); it != context.link_assoc.end(); ) { - if( check_associated(context, *it) ) { - DEBUG("- Consumed associated type rule - " << *it); - it = context.link_assoc.erase(it); + //for(auto it = context.link_assoc.begin(); it != context.link_assoc.end(); ) { + // const auto& rule = *it; + for(unsigned int i = 0; i < context.link_assoc.size(); ) { + const auto& rule = context.link_assoc[i]; + if( check_associated(context, rule) ) { + DEBUG("- Consumed associated type rule - " << rule); + context.link_assoc.erase( context.link_assoc.begin() + i ); + //it = context.link_assoc.erase(it); } else { - ++ it; + //++ it; + i ++; } } // 4. Revisit nodes that require revisiting @@ -2751,13 +2789,13 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: } // - Validate typeck - expr = ::HIR::ExprPtr( mv$(root_ptr) ); { DEBUG("==== VALIDATE ===="); context.dump(); ExprVisitor_Apply visitor { context.m_ivars }; - expr->visit( visitor ); + root_ptr->visit( visitor ); } + expr = ::HIR::ExprPtr( mv$(root_ptr) ); } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 9e9467b0..3d069dde 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -269,6 +269,7 @@ void HMTypeInferrence::compact_ivars() if( !v.is_alias() ) { //auto nt = this->expand_associated_types(Span(), v.type->clone()); auto nt = v.type->clone(); + DEBUG("- " << i << " " << *v.type << " -> " << nt); *v.type = mv$(nt); } @@ -418,6 +419,77 @@ void HMTypeInferrence::print_type(::std::ostream& os, const ::HIR::TypeRef& tr) ) } +void HMTypeInferrence::expand_ivars(::HIR::TypeRef& type) +{ + TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e), + (Infer, + const auto& t = this->get_type(type); + if( &t != &type ) { + type = t.clone(); + } + ), + (Diverge, + ), + (Primitive, + ), + (Path, + // Iterate all arguments + TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), + (Generic, + this->expand_ivars_params(e2.m_params); + ), + (UfcsKnown, + this->expand_ivars(*e2.type); + this->expand_ivars_params(e2.trait.m_params); + this->expand_ivars_params(e2.params); + ), + (UfcsUnknown, + this->expand_ivars(*e2.type); + this->expand_ivars_params(e2.params); + ), + (UfcsInherent, + this->expand_ivars(*e2.type); + this->expand_ivars_params(e2.params); + ) + ) + ), + (Generic, + ), + (TraitObject, + // TODO: Iterate all paths + ), + (Array, + this->expand_ivars(*e.inner); + ), + (Slice, + this->expand_ivars(*e.inner); + ), + (Tuple, + for(auto& ty : e) + this->expand_ivars(ty); + ), + (Borrow, + this->expand_ivars(*e.inner); + ), + (Pointer, + this->expand_ivars(*e.inner); + ), + (Function, + // No ivars allowed? + ), + (Closure, + this->expand_ivars(*e.m_rettype); + for(auto& ty : e.m_arg_types) + this->expand_ivars(ty); + ) + ) +} +void HMTypeInferrence::expand_ivars_params(::HIR::PathParams& params) +{ + for(auto& arg : params.m_types) + expand_ivars(arg); +} + void HMTypeInferrence::add_ivars(::HIR::TypeRef& type) { TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e), @@ -887,6 +959,7 @@ void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars) for(auto& v : m_ivars.m_ivars) { if( !v.is_alias() ) { + m_ivars.expand_ivars( *v.type ); // Don't expand unless it is needed if( this->has_associated_type(*v.type) ) { // TODO: cloning is expensive, BUT printing below is nice diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 93fe8cf9..56106cf1 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -99,6 +99,9 @@ public: // Lookup ::HIR::TypeRef& get_type(::HIR::TypeRef& type); const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const; + + void expand_ivars(::HIR::TypeRef& type); + void expand_ivars_params(::HIR::PathParams& params); // Helpers bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const; @@ -110,7 +113,6 @@ private: }; -// NOTE: impl is in expr_context.cpp class TraitResolution { const HMTypeInferrence& m_ivars; |