diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-11 22:05:05 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-11 22:05:05 +0800 |
commit | 312d91ae9b2e55aa1a447d7994468023490bfeb3 (patch) | |
tree | 37e48917ceb9bada08e99a2f30ff7073c95c8456 | |
parent | 59ed1dee6a4777e380982b3b8dd464429d0f423b (diff) | |
download | mrust-312d91ae9b2e55aa1a447d7994468023490bfeb3.tar.gz |
HIR Typecheck - Fix pattern propagation
-rw-r--r-- | src/hir/type.hpp | 3 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 35 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 83 |
3 files changed, 82 insertions, 39 deletions
diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 209e7f94..70a0419d 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -183,6 +183,9 @@ public: static TypeRef new_array(TypeRef inner, ::HIR::ExprPtr size_expr) { return TypeRef(Data::make_Array({box$(mv$(inner)), mv$(size_expr), ~0u})); } + static TypeRef new_path(::HIR::Path path, TypePathBinding binding) { + return TypeRef(Data::make_Path({ mv$(path), mv$(binding) })); + } TypeRef clone() const; diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index c54be433..cc7fa04a 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -341,8 +341,10 @@ namespace typeck { this->context.add_binding(node.span(), pat, node.m_value->m_res_type); } } + DEBUG("- match val : " << this->context.get_type(node.m_value->m_res_type)); ::HIR::ExprVisitorDef::visit(node); + DEBUG("- match val : " << this->context.get_type(node.m_value->m_res_type)); } void visit(::HIR::ExprNode_If& node) override { @@ -428,6 +430,7 @@ namespace typeck { // - Variable: Bind to same ivar void visit(::HIR::ExprNode_Variable& node) override { + TRACE_FUNCTION_F("var #"<<node.m_slot<<" '"<<node.m_name<<"'"); this->context.apply_equality(node.span(), node.m_res_type, this->context.get_var_type(node.span(), node.m_slot)); } @@ -530,11 +533,14 @@ namespace typeck { // - Match: all branches match void visit(::HIR::ExprNode_Match& node) override { - TRACE_FUNCTION_F("match ..."); + TRACE_FUNCTION_F("match (...: " << this->context.get_type(node.m_value->m_res_type) << ")"); for(auto& arm : node.m_arms) { DEBUG("ARM " << arm.m_patterns); + for(auto& pat : arm.m_patterns) { + this->context.apply_pattern(/*node.span(),*/ pat, node.m_value->m_res_type); + } // TODO: Span on the arm this->context.apply_equality(node.span(), node.m_res_type, arm.m_code->m_res_type, &arm.m_code); } @@ -1436,17 +1442,20 @@ namespace typeck { ) } - if( node.m_args.size() + 1 != node.m_arg_types.size() ) { - ERROR(node.span(), E0000, "Incorrect number of arguments when calling " << ty); - } - - for( unsigned int i = 0; i < node.m_args.size(); i ++ ) + if( node.m_arg_types.size() > 0 ) { - auto& arg_node = node.m_args[i]; - this->context.apply_equality(node.span(), node.m_arg_types[i], arg_node->m_res_type, &arg_node); + if( node.m_args.size() + 1 != node.m_arg_types.size() ) { + ERROR(node.span(), E0000, "Incorrect number of arguments when calling " << ty); + } + + for( unsigned int i = 0; i < node.m_args.size(); i ++ ) + { + auto& arg_node = node.m_args[i]; + this->context.apply_equality(node.span(), node.m_arg_types[i], arg_node->m_res_type, &arg_node); + } + // TODO: Allow infer + this->context.apply_equality(node.span(), node.m_res_type, node.m_arg_types.back()); } - // TODO: Allow infer - this->context.apply_equality(node.span(), node.m_res_type, node.m_arg_types.back()); ::HIR::ExprVisitorDef::visit(node); } @@ -1574,7 +1583,7 @@ namespace typeck { { // TODO: How to apply deref coercions here? // - Don't need to, instead construct "higher" nodes to avoid it - TRACE_FUNCTION_F("var #"<<node.m_slot<<" '"<<node.m_name<<"'"); + TRACE_FUNCTION_F("var #"<<node.m_slot<<" '"<<node.m_name<<"' = " << this->context.get_type(node.m_res_type)); this->context.apply_equality(node.span(), node.m_res_type, this->context.get_var_type(node.span(), node.m_slot) ); @@ -1592,7 +1601,8 @@ namespace typeck { const auto& str = this->context.m_crate.get_struct_by_path(node.span(), node.m_path.m_path); this->fix_param_count(node.span(), node.m_path.clone(), str.m_params, node.m_path.m_params); - this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef(node.m_path.clone())); + auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_Path { node.m_path.clone(), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) } ); + this->context.apply_equality(node.span(), node.m_res_type, ty); if( !str.m_data.is_Named() ) ERROR(sp, E0000, "Struct literal constructor for non-struct-like struct"); @@ -1792,7 +1802,6 @@ void Typecheck_Code(typeck::TypecheckContext context, const ::HIR::TypeRef& resu // 3. Check that there's no unresolved types left expr = ::HIR::ExprPtr( mv$(root_ptr) ); - context.compact_ivars(); context.dump(); { DEBUG("==== VALIDATE ===="); diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 4a5e15a9..5edf8b80 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -34,8 +34,28 @@ void typeck::TypecheckContext::compact_ivars() DEBUG("- " << i << " " << *v.type << " -> " << nt); *v.type = mv$(nt); } + else { + + auto index = v.alias; + unsigned int count = 0; + assert(index < m_ivars.size()); + while( m_ivars.at(index).is_alias() ) { + index = m_ivars.at(index).alias; + + if( count >= 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 ++; } + + for(auto& v : m_locals) { + v.type = this->get_type(v.type).clone(); + } } void typeck::TypecheckContext::add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type) @@ -173,17 +193,18 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, ), (Ref, if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Borrow({ e.type, box$(this->new_ivar_tr()) }); + this->apply_equality(sp, type, ::HIR::TypeRef::new_borrow( e.type, this->new_ivar_tr() )); + type = this->get_type(type).clone(); } // Type must be a &-ptr TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected &-ptr, got " << type); ), (Infer, throw "";), (Borrow, if( te.type != e.type ) { - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected &-ptr, got " << type); } this->add_binding(sp, *e.sub, *te.inner ); ) @@ -194,16 +215,17 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, ::std::vector< ::HIR::TypeRef> sub_types; for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) sub_types.push_back( this->new_ivar_tr() ); - type.m_data = ::HIR::TypeRef::Data::make_Tuple( mv$(sub_types) ); + this->apply_equality(sp, type, ::HIR::TypeRef( mv$(sub_types) )); + type = this->get_type(type).clone(); } TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected tuple, got " << type); ), (Infer, throw ""; ), (Tuple, if( te.size() != e.sub_patterns.size() ) { - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected " << e.sub_patterns.size() << "-tuple, got " << type); } for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) this->add_binding(sp, e.sub_patterns[i], te[i] ); @@ -212,12 +234,12 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, ), (Slice, if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Slice( {box$(this->new_ivar_tr())} ); - this->mark_change(); + this->apply_equality(sp, type, ::HIR::TypeRef::new_slice( this->new_ivar_tr() )); + type = this->get_type(type).clone(); } TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected slice, got " << type); ), (Infer, throw""; ), (Slice, @@ -228,12 +250,12 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, ), (SplitSlice, if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Slice( {box$(this->new_ivar_tr())} ); - this->mark_change(); + this->apply_equality(sp, type, ::HIR::TypeRef::new_slice( this->new_ivar_tr() )); + type = this->get_type(type).clone(); } TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected slice, got " << type); ), (Infer, throw ""; ), (Slice, @@ -252,7 +274,8 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, (StructTuple, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Path( {e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)} ); + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); + type = this->get_type(type).clone(); } assert(e.binding); const auto& str = *e.binding; @@ -262,7 +285,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Pattern-type mismatch, expected struct, got " << type); ), (Infer, throw ""; ), (Path, @@ -293,7 +316,8 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, (StructTupleWildcard, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Path( {e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)} ); + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); + type = this->get_type(type).clone(); } assert(e.binding); const auto& str = *e.binding; @@ -315,7 +339,8 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, (Struct, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { - type.m_data = ::HIR::TypeRef::Data::make_Path( {e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)} ); + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); + type = this->get_type(type).clone(); } assert(e.binding); const auto& str = *e.binding; @@ -358,7 +383,9 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, if( type.m_data.is_Infer() ) { auto path = e.path.clone(); path.m_path.m_components.pop_back(); - type.m_data = ::HIR::TypeRef::Data::make_Path( {mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)} ); + + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); + type = this->get_type(type).clone(); } assert(e.binding_ptr); const auto& enm = *e.binding_ptr; @@ -399,7 +426,9 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, if( type.m_data.is_Infer() ) { auto path = e.path.clone(); path.m_path.m_components.pop_back(); - type.m_data = ::HIR::TypeRef::Data::make_Path( {mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)} ); + + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); + type = this->get_type(type).clone(); } assert(e.binding_ptr); const auto& enm = *e.binding_ptr; @@ -423,7 +452,9 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, if( type.m_data.is_Infer() ) { auto path = e.path.clone(); path.m_path.m_components.pop_back(); - type.m_data = ::HIR::TypeRef::Data::make_Path( {mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)} ); + + this->apply_equality( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); + type = this->get_type(type).clone(); } assert(e.binding_ptr); const auto& enm = *e.binding_ptr; @@ -481,15 +512,15 @@ void typeck::TypecheckContext::apply_pattern(const ::HIR::Pattern& pat, ::HIR::T // Just leave it, the pattern says nothing about the type ), (Value, - TODO(sp, "Value pattern"); + //TODO(sp, "Value pattern"); ), (Range, - TODO(sp, "Range pattern"); + //TODO(sp, "Range pattern"); ), // - Pointer destructuring (Box, // Type must be box-able - TODO(sp, "Box patterns"); + //TODO(sp, "Box patterns"); ), (Ref, if( ty.m_data.is_Infer() ) { @@ -1080,10 +1111,6 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, (Primitive, ), (Path, - // - Only try resolving if the binding isn't known - if( !e.binding.is_Unbound() ) - return input; - TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), (Generic, for(auto& arg : e2.m_params.m_types) @@ -1093,6 +1120,10 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, TODO(sp, "Path - UfcsInherent - " << e.path); ), (UfcsKnown, + // - Only try resolving if the binding isn't known + if( !e.binding.is_Unbound() ) + return input; + DEBUG("Locating associated type for " << e.path); *e2.type = expand_associated_types(sp, mv$(*e2.type)); |