summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/expr.hpp3
-rw-r--r--src/hir/from_ast_expr.cpp3
-rw-r--r--src/hir_typeck/expr_cs.cpp35
-rw-r--r--src/hir_typeck/helpers.cpp4
4 files changed, 36 insertions, 9 deletions
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index d3bc8ad0..569f1b9d 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -107,7 +107,8 @@ struct ExprNode_Loop:
::HIR::ExprNodeP m_code;
ExprNode_Loop(Span sp, ::std::string label, ::HIR::ExprNodeP code):
- ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()),
+ //ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()),
+ ExprNode(mv$(sp), ::HIR::TypeRef()),
m_label( mv$(label) ),
m_code( mv$(code) )
{}
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index b3251e20..d0877c5f 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -295,7 +295,6 @@ struct LowerHIR_ExprNode_Visitor:
v.m_label,
LowerHIR_ExprNode_Inner(*v.m_code)
) );
- assert( m_rv->m_res_type.m_data.is_Tuple() );
break;
case ::AST::ExprNode_Loop::WHILE: {
::std::vector< ::HIR::ExprNodeP> code;
@@ -311,7 +310,6 @@ struct LowerHIR_ExprNode_Visitor:
v.m_label,
::HIR::ExprNodeP(new ::HIR::ExprNode_Block( v.span(), false, mv$(code)))
) );
- assert( m_rv->m_res_type.m_data.is_Tuple() );
break; }
case ::AST::ExprNode_Loop::WHILELET: {
::std::vector< ::HIR::ExprNode_Match::Arm> arms;
@@ -336,7 +334,6 @@ struct LowerHIR_ExprNode_Visitor:
mv$(arms)
))
) );
- assert( m_rv->m_res_type.m_data.is_Tuple() );
break; }
case ::AST::ExprNode_Loop::FOR:
// NOTE: This should already be desugared (as a pass before resolve)
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index abe418a7..9d2af58e 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -461,6 +461,8 @@ namespace {
::std::vector<bool> inner_coerce_enabled_stack;
+ ::std::vector<const ::HIR::ExprNode_Loop*> loop_blocks; // Used for `break` type markings
+
// TEMP: List of in-scope traits for buildup
::HIR::t_trait_list m_traits;
public:
@@ -557,19 +559,44 @@ namespace {
{
auto _ = this->push_inner_coerce_scoped(false);
TRACE_FUNCTION_F(&node << " loop { ... }");
+ // Push this node to a stack so `break` statements can update the yeilded value
+ this->loop_blocks.push_back( &node );
- this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
- // TODO: This is more correct, but could cause variables to be falsely marked as !
- //this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge());
+ // TODO: This only yields unit if it terminates - otherwise it's !
+ // - There's an RFC proposal (that's on track to be accepted) that allows `break value;`
+ // NOTE: This doesn't set the ivar to !, but marks it as a ! ivar (similar to the int/float markers)
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge());
this->context.add_ivars(node.m_code->m_res_type);
this->context.equate_types(node.span(), node.m_code->m_res_type, ::HIR::TypeRef::new_unit());
node.m_code->visit( *this );
+
+ this->loop_blocks.pop_back( );
}
void visit(::HIR::ExprNode_LoopControl& node) override
{
TRACE_FUNCTION_F(&node << " " << (node.m_continue ? "continue" : "break") << " '" << node.m_label);
- // Nothing
+ // Break types
+ if( !node.m_continue )
+ {
+ if( this->loop_blocks.empty() ) {
+ ERROR(node.span(), E0000, "Break statement with no acive loop");
+ }
+ if( node.m_label != "" )
+ {
+ auto it = ::std::find_if(this->loop_blocks.rbegin(), this->loop_blocks.rend(), [&](const auto& np){ return np->m_label == node.m_label; });
+ if( it == this->loop_blocks.rend() ) {
+ ERROR(node.span(), E0000, "Could not find loop '" << node.m_label << " for break");
+ }
+ const auto& loop_node = **it;
+ this->context.equate_types(node.span(), loop_node.m_res_type, ::HIR::TypeRef::new_unit());
+ }
+ else
+ {
+ const auto& loop_node = *this->loop_blocks.back();
+ this->context.equate_types(node.span(), loop_node.m_res_type, ::HIR::TypeRef::new_unit());
+ }
+ }
}
void visit(::HIR::ExprNode_Let& node) override
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index cc580a58..ade4cf6d 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2292,6 +2292,8 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
}
const auto& ty = *ty_p;
DEBUG("[find_trait_impls_crate] - Compare " << ty << " and " << assoc_bound.second << ", matching generics");
+ // `ty` = Monomorphised actual type (< `be.type` as `be.trait` >::`assoc_bound.first`)
+ // `assoc_bound.second` = Desired type (monomorphised too)
auto cmp = assoc_bound.second .match_test_generics_fuzz(sp, ty, cb_infer, cb_match);
switch(cmp)
{
@@ -2299,7 +2301,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
DEBUG("Equal");
continue;
case ::HIR::Compare::Unequal:
- DEBUG("Assoc failure - " << ty << " != " << assoc_bound.second);
+ DEBUG("Assoc " << assoc_bound.first << " failure - " << ty << " != " << assoc_bound.second);
return false;
case ::HIR::Compare::Fuzzy:
// TODO: When a fuzzy match is encountered on a conditional bound, returning `false` can lead to an false negative (and a compile error)