diff --git a/releasenotes.md b/releasenotes.md index deb0074c0..82fd7372b 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -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 diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 502258653..21f10d3ee 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -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"); diff --git a/test/test_suite/compile_time_introspection/defined_subscript_assign.c3 b/test/test_suite/compile_time_introspection/defined_subscript_assign.c3 new file mode 100644 index 000000000..ee696e61a --- /dev/null +++ b/test/test_suite/compile_time_introspection/defined_subscript_assign.c3 @@ -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; \ No newline at end of file