summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-11 22:05:05 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-11 22:05:05 +0800
commit312d91ae9b2e55aa1a447d7994468023490bfeb3 (patch)
tree37e48917ceb9bada08e99a2f30ff7073c95c8456
parent59ed1dee6a4777e380982b3b8dd464429d0f423b (diff)
downloadmrust-312d91ae9b2e55aa1a447d7994468023490bfeb3.tar.gz
HIR Typecheck - Fix pattern propagation
-rw-r--r--src/hir/type.hpp3
-rw-r--r--src/hir_typeck/expr.cpp35
-rw-r--r--src/hir_typeck/expr_context.cpp83
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));