diff --git a/releasenotes.md b/releasenotes.md index a2914a20c..7a755581c 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -64,6 +64,7 @@ - Compiler segfault when using distinct type in attribute imported from other module #2234. - Assert casting bitstruct to short/char #2237. - @tag didn't work with members #2236. +- Assert comparing untyped lists #2240. ### Stdlib changes - Deprecate `String.is_zstr` and `String.quick_zstr` #2188. diff --git a/src/compiler/number.c b/src/compiler/number.c index 13a7b33f0..80d5e5f6b 100644 --- a/src/compiler/number.c +++ b/src/compiler/number.c @@ -208,11 +208,9 @@ bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp is_eq = !memcmp(left->bytes.ptr, right->bytes.ptr, left->bytes.len); goto RETURN; case CONST_SLICE: - return false; case CONST_INITIALIZER: - return false; case CONST_UNTYPED_LIST: - return false; + UNREACHABLE; case CONST_MEMBER: is_eq = left->member.decl == right->member.decl; goto RETURN; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 119dfa646..4f240eeb5 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -7650,16 +7650,13 @@ static bool sema_expr_analyse_and_or(SemaContext *context, Expr *expr, Expr *lef return true; } - - - static bool sema_binary_is_unsigned_always_same_comparison(SemaContext *context, Expr *expr, Expr *left, Expr *right, Type *lhs_type, Type *rhs_type) { if (context->active_scope.flags & (SCOPE_MACRO | SCOPE_ENSURE | SCOPE_ENSURE_MACRO)) return true; if (!sema_cast_const(left) && !sema_cast_const(right)) return true; if (!type_is_integer(left->type)) return true; - if (expr_is_const(left) && type_is_unsigned(rhs_type)) + if (expr_is_const_int(left) && type_is_unsigned(rhs_type)) { if (int_is_neg(left->const_expr.ixx)) { @@ -7685,7 +7682,7 @@ static bool sema_binary_is_unsigned_always_same_comparison(SemaContext *context, return true; } } - if (!expr_is_const(right) || !type_is_unsigned(lhs_type)) return true; + if (!expr_is_const_int(right) || !type_is_unsigned(lhs_type)) return true; if (int_is_neg(right->const_expr.ixx)) { SEMA_ERROR(right, "Comparing an unsigned value with a negative constant is only allowed inside of macros."); @@ -7807,6 +7804,10 @@ NEXT: RETURN_SEMA_ERROR(expr, "Vector types can only be tested for equality, for other comparison, use vector comparison functions."); } + if (max == type_untypedlist) + { + RETURN_SEMA_ERROR(expr, "Both sides are untyped and cannot be compared. Please cast one or both sides to a type, e.g. (Foo){ 1, 2 } == { 1, 2 }."); + } if (!type_is_comparable(max)) { CHECK_ON_DEFINED(failed_ref); diff --git a/src/compiler/types.c b/src/compiler/types.c index 1e699d028..1bdc1107f 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -511,6 +511,7 @@ bool type_is_comparable(Type *type) case TYPE_FLEXIBLE_ARRAY: case TYPE_OPTIONAL: case TYPE_MEMBER: + case TYPE_UNTYPED_LIST: return false; case TYPE_UNION: case TYPE_STRUCT: @@ -540,7 +541,6 @@ bool type_is_comparable(Type *type) case TYPE_ENUM: case TYPE_FUNC_PTR: case TYPE_FUNC_RAW: - case TYPE_UNTYPED_LIST: case TYPE_TYPEINFO: case TYPE_VECTOR: case TYPE_WILDCARD: diff --git a/test/test_suite/expressions/comparing_untyped.c3 b/test/test_suite/expressions/comparing_untyped.c3 new file mode 100644 index 000000000..9dafabcbd --- /dev/null +++ b/test/test_suite/expressions/comparing_untyped.c3 @@ -0,0 +1,5 @@ +fn int main() +{ + assert({0, 1, 2} == {0, 1, 2}, "Slices must be equivalent"); // #error: Both sides are untyped and cannot be compared + return 0; +} \ No newline at end of file