diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-05 20:59:28 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-05 20:59:28 +0800 |
commit | 7cca8350a22dbc3763db444e9aec459d457962ac (patch) | |
tree | c228c18301f2e8702b230e76630a7e844fe428e9 /src | |
parent | dde5cfa67d37cc89738205684d6c4c3e6988bf19 (diff) | |
download | mrust-7cca8350a22dbc3763db444e9aec459d457962ac.tar.gz |
HIR Typecheck CS - Fix failure of single option inferrence, start on associate types
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 29 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 121 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 31 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 2 |
4 files changed, 147 insertions, 36 deletions
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 1ef16035..07dddc45 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -27,33 +27,8 @@ void typeck::TypecheckContext::dump() const void typeck::TypecheckContext::compact_ivars() { TRACE_FUNCTION; - //m_ivars.compact_ivars([&](const ::HIR::TypeRef& t)->auto{ return this->expand_associated_types(Span(), t.clone); }); - unsigned int i = 0; - for(auto& v : m_ivars.m_ivars) - { - if( !v.is_alias() ) { - auto nt = this->expand_associated_types(Span(), v.type->clone()); - DEBUG("- " << i << " " << *v.type << " -> " << nt); - *v.type = mv$(nt); - } - else { - - auto index = v.alias; - unsigned int count = 0; - assert(index < m_ivars.m_ivars.size()); - while( m_ivars.m_ivars.at(index).is_alias() ) { - index = m_ivars.m_ivars.at(index).alias; - - if( count >= m_ivars.m_ivars.size() ) { - this->dump(); - BUG(Span(), "Loop detected in ivar list when starting at " << v.alias << ", current is " << index); - } - count ++; - } - v.alias = index; - } - i ++; - } + + this->m_resolve.compact_ivars(this->m_ivars); for(auto& v : m_locals) { v.type = this->get_type(v.type).clone(); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 8aeca858..cbb6ab9a 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -40,12 +40,12 @@ struct Context ::HIR::TypeRef left_ty; ::HIR::SimplePath trait; - ::std::vector< ::HIR::TypeRef> params; + ::HIR::PathParams params; ::HIR::TypeRef impl_ty; const char* 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; + os << v.left_ty << " = " << "<" << v.impl_ty << " as " << v.trait << v.params << ">::" << v.name; return os; } }; @@ -402,6 +402,7 @@ namespace { this->context.add_ivars( node.m_cond->m_res_type ); this->context.equate_types_coerce(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond); + node.m_cond->visit( *this ); this->context.add_ivars( node.m_true->m_res_type ); this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_true); @@ -545,7 +546,7 @@ namespace { case ::HIR::ExprNode_UniOp::Op::Invert: this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "not"), {}, node.m_value->m_res_type.clone(), "Output"); case ::HIR::ExprNode_UniOp::Op::Negate: - this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "minus"), {}, node.m_value->m_res_type.clone(), "Output"); + this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "neg"), {}, node.m_value->m_res_type.clone(), "Output"); break; } node.m_value->visit( *this ); @@ -1848,11 +1849,13 @@ void Context::equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR } void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::std::vector< ::HIR::TypeRef> ty_args, const ::HIR::TypeRef& impl_ty, const char *name) { + ::HIR::PathParams pp; + pp.m_types = mv$(ty_args); this->link_assoc.push_back(Associated { l.clone(), trait.clone(), - mv$(ty_args), + mv$(pp), impl_ty.clone(), name }); @@ -1862,6 +1865,11 @@ void Context::add_revisit(::HIR::ExprNode& node) { } void Context::possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef& t) { + { + ::HIR::TypeRef ty_l; + ty_l.m_data.as_Infer().index = ivar_index; + assert( m_ivars.get_type(ty_l).m_data.is_Infer() ); + } if( ivar_index >= possible_ivar_vals.size() ) { possible_ivar_vals.resize( ivar_index + 1 ); } @@ -2195,7 +2203,95 @@ namespace { bool check_associated(Context& context, const Context::Associated& v) { - TODO(Span(), "Typecheck_Code_CS - Associated " << v.left_ty); + TODO(Span(), "check_associated - " << v); + + #if 0 + // Search for ops trait impl + const ::HIR::TraitImpl* impl_ptr = nullptr; + unsigned int count = 0; + DEBUG("Searching for impl " << ops_trait << "< " << ty_right << "> for " << ty_left); + bool found_bound = this->context.find_trait_impls_bound(sp, ops_trait, ops_trait_pp, ty_left, + [&](const auto& args, const auto& assoc) { + assert(args.m_types.size() == 1); + const auto& arg_type = args.m_types[0]; + // TODO: if arg_type mentions Self? + auto cmp = arg_type.compare_with_placeholders(node.span(), ty_right, this->context.callback_resolve_infer()); + if( cmp == ::HIR::Compare::Unequal ) { + DEBUG("- (fail) bounded impl " << ops_trait << "<" << arg_type << "> (ty_right = " << this->context.get_type(ty_right)); + return false; + } + count += 1; + if( cmp == ::HIR::Compare::Equal ) { + return true; + } + else { + if( possible_right_type == ::HIR::TypeRef() ) { + DEBUG("- Set possibility for " << ty_right << " - " << arg_type); + possible_right_type = arg_type.clone(); + } + + return false; + } + }); + // - Only set found_exact if either found_bound returned true, XOR this returns true + bool found_exact = found_bound ^ this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(), + [&](const auto& impl) { + assert( impl.m_trait_args.m_types.size() == 1 ); + const auto& arg_type = impl.m_trait_args.m_types[0]; + + DEBUG("impl" << impl.m_params.fmt_args() << " " << ops_trait << impl.m_trait_args << " for " << impl.m_type); + + bool fail = false; + bool fuzzy = false; + ::std::vector< const ::HIR::TypeRef*> impl_params; + impl_params.resize( impl.m_params.m_types.size() ); + auto cb = [&](auto idx, const auto& ty) { + DEBUG("[_BinOp] " << idx << " = " << ty); + assert( idx < impl_params.size() ); + if( ! impl_params[idx] ) { + impl_params[idx] = &ty; + } + else { + switch( impl_params[idx]->compare_with_placeholders(node.span(), ty, this->context.callback_resolve_infer()) ) + { + case ::HIR::Compare::Unequal: + fail = true; + break; + case ::HIR::Compare::Fuzzy: + fuzzy = true; + break; + case ::HIR::Compare::Equal: + break; + } + } + }; + fail |= !impl.m_type.match_test_generics(sp, ty_left, this->context.callback_resolve_infer(), cb); + fail |= !arg_type.match_test_generics(sp, ty_right, this->context.callback_resolve_infer(), cb); + if( fail ) { + return false; + } + count += 1; + impl_ptr = &impl; + if( !fuzzy ) { + DEBUG("Operator impl exact match - '"<<item_name<<"' - " << arg_type << " == " << ty_right); + return true; + } + else { + DEBUG("Operator impl fuzzy match - '"<<item_name<<"' - " << arg_type << " == " << ty_right); + if( possible_right_type == ::HIR::TypeRef() ) { + DEBUG("- Set possibility for " << ty_right << " - " << arg_type); + possible_right_type = arg_type.clone(); + } + return false; + } + } + ); + // If there wasn't an exact match, BUT there was one partial match - assume the partial match is what we want + if( !found_exact && count == 1 ) { + assert( possible_right_type != ::HIR::TypeRef() ); + this->context.apply_equality(node.span(), possible_right_type, ty_right); + } + #endif } } @@ -2302,21 +2398,28 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: // One possibility, no need to dedup } - if( ivar_ent.types.size() == 1 ) { + ::HIR::TypeRef ty_l_ivar; + ty_l_ivar.m_data.as_Infer().index = i; + const auto& ty_l = context.m_ivars.get_type(ty_l_ivar); + + if( !ty_l.m_data.is_Infer() ) { + DEBUG("- IVar " << ty_l << " had possibilities, but was known"); + } + else if( ivar_ent.types.size() == 1 ) { const ::HIR::TypeRef& ty_r = *ivar_ent.types[0]; - ::HIR::TypeRef ty_l; - ty_l.m_data.as_Infer().index = i; // Only one possibility DEBUG("- IVar " << ty_l << " = " << ty_r); context.equate_types(Span(), ty_l, ty_r); } + else { + } ivar_ent.types.clear(); i ++ ; } count ++; - context.m_ivars.compact_ivars(); + context.m_resolve.compact_ivars(context.m_ivars); } // - Validate typeck diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index bad7e81a..03c38cb0 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -879,6 +879,37 @@ bool TraitResolution::find_trait_impls(const Span& sp, // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- +void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars) +{ + //m_ivars.compact_ivars([&](const ::HIR::TypeRef& t)->auto{ return this->expand_associated_types(Span(), t.clone); }); + unsigned int i = 0; + for(auto& v : m_ivars.m_ivars) + { + if( !v.is_alias() ) { + auto nt = this->expand_associated_types(Span(), v.type->clone()); + DEBUG("- " << i << " " << *v.type << " -> " << nt); + *v.type = mv$(nt); + } + else { + + auto index = v.alias; + unsigned int count = 0; + assert(index < m_ivars.m_ivars.size()); + while( m_ivars.m_ivars.at(index).is_alias() ) { + index = m_ivars.m_ivars.at(index).alias; + + if( count >= m_ivars.m_ivars.size() ) { + this->m_ivars.dump(); + BUG(Span(), "Loop detected in ivar list when starting at " << v.alias << ", current is " << index); + } + count ++; + } + v.alias = index; + } + i ++; + } +} + ::HIR::TypeRef TraitResolution::expand_associated_types(const Span& sp, ::HIR::TypeRef input) const { TRACE_FUNCTION_F(input); diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 005186cc..ec33bd78 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -130,6 +130,8 @@ public: typedef ::std::function<bool(const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl; + void compact_ivars(HMTypeInferrence& m_ivars); + /// Check if a trait bound applies, using the passed function to expand Generic/Infer types bool check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, t_cb_generic placeholder) const; |