Skip to content

Commit 83fd24f

Browse files
committed
Improve error on unsigned implicit conversion to signed.
1 parent 1d4ad5f commit 83fd24f

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

releasenotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Improve error message when doing a rethrow in a function that doesn't return an optional.
1414
- Add `--list-asm` to view all supported `asm` instructions.
1515
- Formatting option "%h" now supports pointers.
16+
- Improve error on unsigned implicit conversion to signed.
1617

1718
### Fixes
1819
- mkdir/rmdir would not work properly with substring paths on non-windows platforms.

src/compiler/sema_expr.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7134,6 +7134,22 @@ static bool sema_replace_with_overload(SemaContext *context, Expr *expr, Expr *l
71347134
return true;
71357135
}
71367136

7137+
static inline bool sema_check_untyped_promotion(SemaContext *context, Expr *expr, bool is_left, CanonicalType *max_flat, Type *max)
7138+
{
7139+
Type *flat = type_flatten(expr->type);
7140+
if (!type_is_unsigned(flat) || type_size(max_flat) != type_size(flat)) return true;
7141+
if (sema_cast_const(expr) && expr_is_const_int(expr) && expr_const_will_overflow(&expr->const_expr, max_flat->type_kind))
7142+
{
7143+
RETURN_SEMA_ERROR(expr,
7144+
"This expression (%s) will be implicitly converted to a signed type due to the %s-hand side being signed, but the value does not fit %s. "
7145+
"To fix this, either cast the value explicitly, or make the %s-hand side an unsigned type.",
7146+
expr_const_to_error_string(&expr->const_expr), is_left ? "right" : "left", type_quoted_error_string(max),
7147+
is_left ? "right" : "left");
7148+
}
7149+
7150+
return true;
7151+
7152+
}
71377153
static bool sema_binary_arithmetic_promotion(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type,
71387154
Expr *parent, const char *error_message, bool allow_bool_vec,
71397155
OperatorOverload *operator_overload_ref,
@@ -7155,6 +7171,12 @@ static bool sema_binary_arithmetic_promotion(SemaContext *context, Expr *left, E
71557171
}
71567172
RETURN_SEMA_ERROR(parent, error_message, type_quoted_error_string(left->type), type_quoted_error_string(right->type));
71577173
}
7174+
Type *flat_max = type_flatten(max);
7175+
if (type_is_signed(flat_max))
7176+
{
7177+
if (!sema_check_untyped_promotion(context, left, true, flat_max, max)) return false;
7178+
if (!sema_check_untyped_promotion(context, right, false, flat_max, max)) return false;
7179+
}
71587180
return cast_implicit_binary(context, left, max, failed_ref) &&
71597181
cast_implicit_binary(context, right, max, failed_ref);
71607182
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn int main()
2+
{
3+
ulong x = ulong.max - 1; // #error: This expression (18446744073709551615) will be implicitly converted to a signed type due to the right-hand side being signed
4+
ulong x1 = -1 + ulong.max; // #error: converted to a signed type due to the left-hand side being signed, but the value does
5+
return 0;
6+
}

0 commit comments

Comments
 (0)