فهرست منبع

Fix `update_untyped_expr_type` for ternary if expressions with an untyped type

gingerBill 3 سال پیش
والد
کامیت
504ea7deeb
1فایلهای تغییر یافته به همراه25 افزوده شده و 4 حذف شده
  1. 25 4
      src/check_expr.cpp

+ 25 - 4
src/check_expr.cpp

@@ -1837,11 +1837,12 @@ void check_cast_error_suggestion(CheckerContext *c, Operand *o, Type *type) {
 }
 
 
-void check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
+bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
 	GB_ASSERT(o->mode == Addressing_Constant);
 	ExactValue out_value = o->value;
 	if (is_type_constant_type(type) && check_representable_as_constant(ctx, o->value, type, &out_value)) {
 		o->value = out_value;
+		return true;
 	} else {
 		o->value = out_value;
 
@@ -1866,6 +1867,7 @@ void check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
 			error(o->expr, "Cannot convert '%s' to '%s' from '%s", a, b, c);
 			check_assignment_error_suggestion(ctx, o, type);
 		}
+		return false;
 	}
 }
 
@@ -3204,6 +3206,16 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
 	x->mode = Addressing_Value;
 }
 
+Operand make_operand_from_node(Ast *node) {
+	GB_ASSERT(node != nullptr);
+	Operand x = {};
+	x.expr  = node;
+	x.mode  = node->tav.mode;
+	x.type  = node->tav.type;
+	x.value = node->tav.value;
+	return x;
+}
+
 
 void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	GB_ASSERT(e != nullptr);
@@ -3252,9 +3264,18 @@ void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final)
 			// See above note in UnaryExpr case
 			break;
 		}
-
-		update_untyped_expr_type(c, te->x, type, final);
-		update_untyped_expr_type(c, te->y, type, final);
+		
+		// NOTE(bill): This is a bit of a hack to get around the edge cases of ternary if expressions
+		// having an untyped value
+		Operand x = make_operand_from_node(te->x);
+		Operand y = make_operand_from_node(te->y);		
+		if (x.mode != Addressing_Constant || check_is_expressible(c, &x, type)) {
+			update_untyped_expr_type(c, te->x, type, final);
+		}
+		if (y.mode != Addressing_Constant || check_is_expressible(c, &y, type)) {
+			update_untyped_expr_type(c, te->y, type, final);
+		}
+		
 	case_end;
 
 	case_ast_node(te, TernaryWhenExpr, e);