summaryrefslogtreecommitdiff
path: root/src/hir_typeck/expr_check.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-11-26 18:28:08 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-11-26 18:28:08 +0800
commitad4d5ab92a8317428e066b70977333be106abaa0 (patch)
tree1d6f34f219d2f77fb5c85526f9bc6a23bb8e9604 /src/hir_typeck/expr_check.cpp
parente335207c353efec94963e273d2fc3294afc860e0 (diff)
downloadmrust-ad4d5ab92a8317428e066b70977333be106abaa0.tar.gz
HIR/MIR - Error checking for assigning into ! (as opposed to from !)
Diffstat (limited to 'src/hir_typeck/expr_check.cpp')
-rw-r--r--src/hir_typeck/expr_check.cpp31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index febe8190..985fe15f 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -21,6 +21,7 @@ namespace {
//const t_args& m_args;
const ::HIR::TypeRef& ret_type;
::std::vector< const ::HIR::TypeRef*> closure_ret_types;
+ ::std::vector<const ::HIR::ExprNode_Loop*> m_loops;
::HIR::SimplePath m_lang_Index;
@@ -93,11 +94,37 @@ namespace {
void visit(::HIR::ExprNode_Loop& node) override
{
TRACE_FUNCTION_F(&node << " loop { ... }");
+ m_loops.push_back(&node);
node.m_code->visit(*this);
+ m_loops.pop_back();
}
void visit(::HIR::ExprNode_LoopControl& node) override
{
- //TRACE_FUNCTION_F(&node << " " << (node.m_continue ? "continue" : "break") << " '" << node.m_label);
+ TRACE_FUNCTION_F(&node << " " << (node.m_continue ? "continue" : "break") << " '" << node.m_label);
+ // TODO: Validate `break` return value
+ if( node.m_value )
+ {
+ node.m_value->visit(*this);
+ }
+
+ if( !node.m_continue )
+ {
+ ::HIR::TypeRef unit = ::HIR::TypeRef::new_unit();
+ const auto& ty = (node.m_value ? node.m_value->m_res_type : unit);
+ const ::HIR::ExprNode_Loop* loop;
+ if( node.m_label == "" ) {
+ ASSERT_BUG(node.span(), !m_loops.empty(), "Break with no loop");
+ loop = m_loops.back();
+ }
+ else {
+ auto it = ::std::find_if( m_loops.rbegin(), m_loops.rend(), [&](const auto* lp){ return lp->m_label == node.m_label; } );
+ ASSERT_BUG(node.span(), it != m_loops.rend(), "Break with no matching loop");
+ loop = *it;
+ }
+
+ DEBUG("Breaking to " << loop << ", type " << loop->m_res_type);
+ check_types_equal(node.span(), loop->m_res_type, ty);
+ }
}
void visit(::HIR::ExprNode_Let& node) override
{
@@ -1023,7 +1050,7 @@ namespace {
}
void check_types_equal(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::TypeRef& r) const
{
- if( l.m_data.is_Diverge() || r.m_data.is_Diverge() ) {
+ if( /*l.m_data.is_Diverge() ||*/ r.m_data.is_Diverge() ) {
// Diverge, matches everything.
// TODO: Is this always true?
}