Allow for foo() or_else unreachable() and other diverging procedures

This commit is contained in:
gingerBill
2022-08-05 12:19:57 +01:00
parent 576914aee1
commit a58e4d0359
3 changed files with 70 additions and 27 deletions

View File

@@ -119,6 +119,7 @@ void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name
void check_or_else_expr_no_value_error(CheckerContext *c, String const &name, Operand const &x, Type *type_hint);
void check_or_return_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_);
bool is_diverging_expr(Ast *expr);
void check_did_you_mean_print(DidYouMeanAnswers *d, char const *prefix = "") {
auto results = did_you_mean_results(d);
@@ -7399,8 +7400,25 @@ ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type
return Expr_Expr;
}
check_multi_expr_with_type_hint(c, &y, default_value, x.type);
error_operand_no_value(&y);
bool y_is_diverging = false;
check_expr_base(c, &y, default_value, x.type);
switch (y.mode) {
case Addressing_NoValue:
if (is_diverging_expr(y.expr)) {
// Allow
y.mode = Addressing_Value;
y_is_diverging = true;
} else {
error_operand_no_value(&y);
y.mode = Addressing_Invalid;
}
break;
case Addressing_Type:
error_operand_not_expression(&y);
y.mode = Addressing_Invalid;
break;
}
if (y.mode == Addressing_Invalid) {
o->mode = Addressing_Value;
o->type = t_invalid;
@@ -7414,7 +7432,9 @@ ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type
add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value);
if (left_type != nullptr) {
check_assignment(c, &y, left_type, name);
if (!y_is_diverging) {
check_assignment(c, &y, left_type, name);
}
} else {
check_or_else_expr_no_value_error(c, name, x, type_hint);
}