mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
$defined(x[0] = val) causes an error instead of returning false when a type does not have []= defined #2454
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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, ¤t_type, ¤t_expr, &subscript_type, &overload, &index_value, false, OVERLOAD_ELEMENT_SET, check_valid))
|
||||
if (!sema_expr_resolve_subscript_index(context, expr, subscripted, index, ¤t_type, ¤t_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");
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user