summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-05 22:38:39 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-05 22:38:39 +0800
commit759ed2bfa35b40c5d54d168324fa43ca9f3c1e01 (patch)
tree60a8cdf4cc10728066aee101562aee96d82aa6d9
parentf67a53724dca999c84b8606a45d5752aa1d154fe (diff)
downloadmrust-759ed2bfa35b40c5d54d168324fa43ca9f3c1e01.tar.gz
HIR Type check - Add check to ensure that all is inferred
-rw-r--r--src/hir_typeck/expr.cpp135
1 files changed, 129 insertions, 6 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index e43845e4..11d7662c 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1170,6 +1170,26 @@ namespace {
::HIR::ExprVisitorDef::visit(node);
}
+
+ void visit(::HIR::ExprNode_UniOp& node) override
+ {
+ ::HIR::ExprVisitorDef::visit(node);
+
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_UniOp::Op::Ref:
+ this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone()));
+ break;
+ case ::HIR::ExprNode_UniOp::Op::RefMut:
+ this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone()));
+ break;
+ case ::HIR::ExprNode_UniOp::Op::Invert:
+ break;
+ case ::HIR::ExprNode_UniOp::Op::Negate:
+ break;
+ }
+ }
+
void visit(::HIR::ExprNode_Tuple& node) override
{
// Only delete and apply if the return type is an ivar
@@ -1292,6 +1312,19 @@ namespace {
void visit(::HIR::ExprNode_UniOp& node) override
{
::HIR::ExprVisitorDef::visit(node);
+
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_UniOp::Op::Ref:
+ //this->apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone()));
+ break;
+ case ::HIR::ExprNode_UniOp::Op::RefMut:
+ break;
+ case ::HIR::ExprNode_UniOp::Op::Invert:
+ break;
+ case ::HIR::ExprNode_UniOp::Op::Negate:
+ break;
+ }
}
// - Cast: Nothing needs to happen
void visit(::HIR::ExprNode_Cast& node) override
@@ -1337,6 +1370,7 @@ namespace {
void visit(::HIR::ExprNode_Variable& node) override
{
// 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<<"'");
this->context.apply_equality(node.span(),
node.m_res_type, this->context.get_var_type(node.span(), node.m_slot)
@@ -1345,12 +1379,97 @@ namespace {
// - Struct literal: Semi-known types
void visit(::HIR::ExprNode_StructLiteral& node) override
{
+ ::HIR::ExprVisitorDef::visit(node);
}
// - Tuple literal:
void visit(::HIR::ExprNode_Tuple& node) override
{
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ // - Array list
+ void visit(::HIR::ExprNode_ArrayList& node) override
+ {
+ const auto& val_type = *node.m_res_type.m_data.as_Array().inner;
+ ::HIR::ExprVisitorDef::visit(node);
+ for(auto& sn : node.m_vals)
+ this->context.apply_equality(sn->span(), val_type, sn->m_res_type, &sn);
+ }
+ // - Array (sized)
+ void visit(::HIR::ExprNode_ArraySized& node) override
+ {
+ const auto& val_type = *node.m_res_type.m_data.as_Array().inner;
+ ::HIR::ExprVisitorDef::visit(node);
+ this->context.apply_equality(node.span(), val_type, node.m_val->m_res_type, &node.m_val);
+ }
+ // - Closure
+ void visit(::HIR::ExprNode_Closure& node) override
+ {
+ ::HIR::ExprVisitorDef::visit(node);
+ this->context.apply_equality(node.span(), node.m_return, node.m_code->m_res_type, &node.m_code);
+ }
+ };
+
+ /// Visitor that applies the inferred types, and checks that all of them are fully resolved
+ class ExprVisitor_Apply:
+ public ::HIR::ExprVisitorDef
+ {
+ TypecheckContext& context;
+ public:
+ ExprVisitor_Apply(TypecheckContext& context):
+ context(context)
+ {
+ }
+ void visit_node(::HIR::ExprNode& node) override {
+ //node.m_res_type = this->context.get_type(node.m_res_type).clone();
+ this->check_type_resolved(node.span(), node.m_res_type, node.m_res_type);
+ }
+
+ private:
+ void check_type_resolved(const Span& sp, ::HIR::TypeRef& ty, const ::HIR::TypeRef& top_type) const {
+ TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e),
+ (Infer,
+ auto new_ty = this->context.get_type(ty).clone();
+ if( new_ty.m_data.is_Infer() ) {
+ ERROR(sp, E0000, "Failed to infer type " << top_type);
+ }
+ ty = mv$(new_ty);
+ ),
+ (Diverge,
+ // Leaf
+ ),
+ (Primitive,
+ // Leaf
+ ),
+ (Path,
+ // TODO:
+ ),
+ (Generic,
+ // Leaf
+ ),
+ (TraitObject,
+ // TODO:
+ ),
+ (Array,
+ this->check_type_resolved(sp, *e.inner, top_type);
+ ),
+ (Slice,
+ this->check_type_resolved(sp, *e.inner, top_type);
+ ),
+ (Tuple,
+ for(auto& st : e)
+ this->check_type_resolved(sp, st, top_type);
+ ),
+ (Borrow,
+ this->check_type_resolved(sp, *e.inner, top_type);
+ ),
+ (Pointer,
+ this->check_type_resolved(sp, *e.inner, top_type);
+ ),
+ (Function,
+ // TODO:
+ )
+ )
}
- // TODO: Other nodes (propagate/equalize types down)
};
};
@@ -1388,6 +1507,10 @@ void Typecheck_Code(TypecheckContext context, const ::HIR::TypeRef& result_type,
// 3. Check that there's no unresolved types left
// TODO: Check for completed type resolution
context.dump();
+ {
+ ExprVisitor_Apply visitor { context };
+ expr->visit( visitor );
+ }
}
@@ -1485,7 +1608,7 @@ namespace {
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
this->visit_type( *e.inner );
TypecheckContext typeck_context { m_impl_generics, m_item_generics };
- DEBUG("Array size");
+ DEBUG("Array size " << ty);
Typecheck_Code( mv$(typeck_context), ::HIR::TypeRef(::HIR::CoreType::Usize), e.size );
)
else {
@@ -1503,7 +1626,7 @@ namespace {
for( auto& arg : item.m_args ) {
typeck_context.add_binding( arg.first, arg.second );
}
- DEBUG("Function code");
+ DEBUG("Function code " << p);
Typecheck_Code( mv$(typeck_context), item.m_return, item.m_code );
}
}
@@ -1512,7 +1635,7 @@ namespace {
if( item.m_value )
{
TypecheckContext typeck_context { m_impl_generics, m_item_generics };
- DEBUG("Static value");
+ DEBUG("Static value " << p);
Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value );
}
}
@@ -1521,7 +1644,7 @@ namespace {
if( item.m_value )
{
TypecheckContext typeck_context { m_impl_generics, m_item_generics };
- DEBUG("Const value");
+ DEBUG("Const value " << p);
Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value );
}
}
@@ -1536,7 +1659,7 @@ namespace {
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
TypecheckContext typeck_context { m_impl_generics, m_item_generics };
- DEBUG("Enum value");
+ DEBUG("Enum value " << p << " - " << var.first);
Typecheck_Code( mv$(typeck_context), enum_type, e );
)
}