diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-10 17:21:17 +1000 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-10 17:21:17 +1000 |
commit | 5c3de8c392cc9c0a7a5fc858ad3ff33d0f597a04 (patch) | |
tree | e6061ff36e3f1ebaf6b93a3b446a4d6614d4f6bc /src | |
parent | 478c905e5db5dc6ded018e3123b4346de6da0693 (diff) | |
download | mrust-5c3de8c392cc9c0a7a5fc858ad3ff33d0f597a04.tar.gz |
HIR Typecheck CS - Ensure that types that would be revealed by a method call are not defaulted until that call is known
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 8fa36cfa..e860b68c 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -61,6 +61,7 @@ struct Context struct IVarPossible { + bool force_no = false; // TODO: If an ivar is eliminated (i.e. has its type dropped) while its pointer is here - things will break //::std::vector<const ::HIR::TypeRef*> types; ::std::vector<::HIR::TypeRef> types_to; @@ -102,12 +103,16 @@ struct Context void equate_types(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::TypeRef& r); // - Equate two types, allowing inferrence void equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR::ExprNodeP& node_ptr); + // - Mark a type as having an unknown coercion (for this round) + void equate_types_shadow(const Span& sp, const ::HIR::TypeRef& l); // - Equate a type to an associated type (if name == "", no equation is done, but trait is searched) void 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, bool is_op=false); // - List `t` as a possible type for `ivar_index` void possible_equate_type_to(unsigned int ivar_index, const ::HIR::TypeRef& t); void possible_equate_type_from(unsigned int ivar_index, const ::HIR::TypeRef& t); + // Mark an ivar as having an unknown possibility + void possible_equate_type_disable(unsigned int ivar_index); void possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef& t, bool is_to); // - Add a pattern binding (forcing the type to match) @@ -1534,6 +1539,13 @@ namespace { const auto& ty = this->context.get_type(node.m_value->m_res_type); //const auto ty = this->context.m_resolve.expand_associated_types(node.span(), this->context.get_type(node.m_value->m_res_type).clone()); TRACE_FUNCTION_F("(CallMethod) ty = " << this->context.m_ivars.fmt_type(ty)); + + // Make sure that no mentioned types are inferred until this method is known + this->context.equate_types_shadow(node.span(), node.m_res_type); + for( const auto& arg_node : node.m_args ) { + this->context.equate_types_shadow(node.span(), arg_node->m_res_type); + } + // Using autoderef, locate this method on the type ::HIR::Path fcn_path { ::HIR::SimplePath() }; unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, ty, node.m_method, fcn_path); @@ -2332,6 +2344,25 @@ void Context::equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR DEBUG("equate_types_coerce(" << this->link_coerce.back() << ")"); this->m_ivars.mark_change(); } +void Context::equate_types_shadow(const Span& sp, const ::HIR::TypeRef& l) +{ + TU_MATCH_DEF(::HIR::TypeRef::Data, (this->get_type(l).m_data), (e), + ( + ), + (Borrow, + TU_MATCH_DEF(::HIR::TypeRef::Data, (this->get_type(*e.inner).m_data), (e2), + ( + ), + (Infer, + this->possible_equate_type_disable(e2.index); + ) + ) + ), + (Infer, + this->possible_equate_type_disable(e.index); + ) + ) +} 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, bool is_op) { ::HIR::PathParams pp; @@ -2375,6 +2406,20 @@ void Context::possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef //list.push_back( &t ); list.push_back( t.clone() ); } +void Context::possible_equate_type_disable(unsigned int ivar_index) { + DEBUG(ivar_index << " ?= ??"); + { + ::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 ); + } + auto& ent = possible_ivar_vals[ivar_index]; + ent.force_no = true; +} void Context::add_var(unsigned int index, const ::std::string& name, ::HIR::TypeRef type) { if( m_bindings.size() <= index ) @@ -2927,6 +2972,10 @@ namespace { // No idea! (or unused) return ; } + if( ivar_ent.force_no == true ) { + ivar_ent = Context::IVarPossible(); + return ; + } struct H { // De-duplicate list (taking into account other ivars) @@ -2985,6 +3034,7 @@ namespace { else { } + ivar_ent.force_no = false; ivar_ent.types_to.clear(); ivar_ent.types_from.clear(); } |