$defined(x[0] = val) causes an error instead of returning false when a type does not have []= defined #2454

This commit is contained in:
Christoffer Lerno
2025-09-03 00:08:43 +02:00
parent 14a929588a
commit e25812a071
3 changed files with 28 additions and 14 deletions

View File

@@ -7,6 +7,7 @@
### Fixes
- Compiler assert with var x @noinit = 0 #2452
- Confusing error message when type has [] overloaded but not []= #2453
- $defined(x[0] = val) causes an error instead of returning false when a type does not have []= defined #2454
### Stdlib changes

View File

@@ -3909,7 +3909,7 @@ SKIP:
return true;
}
static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr *expr, bool check_valid)
static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr *expr, bool *failed_ref)
{
// Evaluate the expression to index.
Expr *subscripted = exprptr(expr->subscript_expr.expr);
@@ -3948,12 +3948,11 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
Decl *overload;
Type *subscript_type;
int64_t index_value;
if (!sema_expr_resolve_subscript_index(context, expr, subscripted, index, &current_type, &current_expr, &subscript_type, &overload, &index_value, false, OVERLOAD_ELEMENT_SET, check_valid))
if (!sema_expr_resolve_subscript_index(context, expr, subscripted, index, &current_type, &current_expr, &subscript_type, &overload, &index_value, false, OVERLOAD_ELEMENT_SET, failed_ref != NULL))
{
if (check_valid && expr_ok(index))
if (failed_ref && expr_ok(index))
{
expr_poison(expr);
return true;
*failed_ref = true;
}
return false;
}
@@ -3963,7 +3962,7 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
{
if (index_value == -1)
{
if (check_valid) goto VALID_FAIL_POISON;
if (failed_ref) goto VALID_FAIL_POISON;
RETURN_SEMA_ERROR(index, "Assigning to a compile time constant requires a constant index.");
}
expr->expr_kind = EXPR_CT_SUBSCRIPT;
@@ -3982,7 +3981,7 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
Decl *len = sema_find_untyped_operator(current_expr->type, OVERLOAD_LEN, NULL);
if (!len)
{
if (check_valid) goto VALID_FAIL_POISON;
if (failed_ref) goto VALID_FAIL_POISON;
RETURN_SEMA_ERROR(subscripted, "Cannot index '%s' from the end, since there is no 'len' overload.", type_to_error_string(subscripted->type));
}
if (!sema_analyse_expr(context, current_expr)) return false;
@@ -4016,9 +4015,9 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
// Check range
bool remove_from_back = false;
if (!sema_slice_index_is_in_range(context, current_type, index, false, start_from_end, &remove_from_back,
check_valid))
failed_ref != NULL))
{
if (check_valid) goto VALID_FAIL_POISON;
if (failed_ref) goto VALID_FAIL_POISON;
return false;
}
if (remove_from_back)
@@ -4030,8 +4029,8 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
expr->type = type_add_optional(subscript_type, optional);
return true;
VALID_FAIL_POISON:
expr_poison(expr);
return true;
*failed_ref = true;
return false;
}
static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, CheckType check, bool check_valid)
@@ -5963,7 +5962,7 @@ static inline bool sema_expr_analyse_swizzle(SemaContext *context, Expr *expr, E
};
if (is_lvalue)
{
if (!sema_expr_analyse_subscript_lvalue(context, expr, false)) return false;
if (!sema_expr_analyse_subscript_lvalue(context, expr, NULL)) return false;
}
else
{
@@ -9193,7 +9192,7 @@ static inline bool sema_expr_analyse_binary(SemaContext *context, Type *infer_ty
{
if (left->expr_kind != EXPR_TYPEINFO)
{
if (!sema_analyse_expr_lvalue(context, left, NULL)) return false;
if (!sema_analyse_expr_lvalue(context, left, failed_ref)) return false;
}
}
else
@@ -11454,7 +11453,7 @@ RETRY:
case EXPR_CT_IDENT:
return sema_expr_resolve_ct_identifier(context, expr);
case EXPR_SUBSCRIPT:
return sema_expr_analyse_subscript_lvalue(context, expr, false);
return sema_expr_analyse_subscript_lvalue(context, expr, failed_ref);
case EXPR_OTHER_CONTEXT:
{
DEBUG_LOG("Switch context");

View File

@@ -0,0 +1,14 @@
fn int main(String[] args)
{
MyArray a = {{1, 4, 3, 6, 5}};
$assert(!$defined(a[0] = 2));
return 0;
}
struct MyArray
{
int[] val;
}
fn int MyArray.get(self, usz idx) @operator([]) => self.val[idx];
fn usz MyArray.len(self) @operator(len) => self.val.len;