From 03b410c518c7c4a351510c8345aecfaad6ef8751 Mon Sep 17 00:00:00 2001 From: Jackson Wambolt Date: Mon, 2 Jun 2025 20:50:20 -0500 Subject: [PATCH 1/3] Check min/max operand types We weren't checking the types of operands after the first, and then later we were assuming they were all numeric. Closes #24060. --- src/Sema.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Sema.zig b/src/Sema.zig index f051a62af36b..c98bba8d58e7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25140,6 +25140,7 @@ fn analyzeMinMax( } else { for (operands[1..], operand_srcs[1..]) |operand, operand_src| { const operand_ty = sema.typeOf(operand); + try sema.checkNumericType(block, operand_src, operand_ty); if (operand_ty.zigTypeTag(zcu) == .vector) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(operand_srcs[0], "expected vector, found '{}'", .{first_operand_ty.fmt(pt)}); From 037143339d1eb82d9d69a44aa26b260e422e59b8 Mon Sep 17 00:00:00 2001 From: Jackson Wambolt Date: Tue, 3 Jun 2025 22:26:31 +0000 Subject: [PATCH 2/3] Add compile error test --- test/cases/compile_errors/minmax_nonnumeric_operand.zig | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/cases/compile_errors/minmax_nonnumeric_operand.zig diff --git a/test/cases/compile_errors/minmax_nonnumeric_operand.zig b/test/cases/compile_errors/minmax_nonnumeric_operand.zig new file mode 100644 index 000000000000..7c74c38aa660 --- /dev/null +++ b/test/cases/compile_errors/minmax_nonnumeric_operand.zig @@ -0,0 +1,9 @@ +comptime { + _ = @min(0, false); +} + +// error +// backend=stage2 +// target=native +// +// :2:17: error: expected number, found 'bool' From d62ba8d0759239f8ab69cd2557074f6a3fb17cff Mon Sep 17 00:00:00 2001 From: Jackson Wambolt Date: Thu, 12 Jun 2025 00:09:57 +0000 Subject: [PATCH 3/3] Add test cases for other non-numeric types --- .../minmax_nonnumeric_operand.zig | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/test/cases/compile_errors/minmax_nonnumeric_operand.zig b/test/cases/compile_errors/minmax_nonnumeric_operand.zig index 7c74c38aa660..7100879b5b90 100644 --- a/test/cases/compile_errors/minmax_nonnumeric_operand.zig +++ b/test/cases/compile_errors/minmax_nonnumeric_operand.zig @@ -1,9 +1,41 @@ -comptime { - _ = @min(0, false); -} +// zig fmt: off +comptime { _ = @min(0, u32); } // type +comptime { _ = @max(0, {}); } // void +comptime { _ = @min(0, false); } // boolean +comptime { _ = @min(0, &@as(u8, 0)); } // pointer +comptime { _ = @max(0, [0]u8{}); } // array +comptime { _ = @min(0, Struct{}); } // struct +comptime { _ = @max(0, null); } // null +comptime { _ = @min(0, @as(?u8, 0)); } // nullable +comptime { _ = @max(0, @as(error{}!u8, 0)); } // error union +comptime { _ = @min(0, error.Foo); } // error set +comptime { _ = @max(0, Enum.foo); } // enum +comptime { _ = @min(0, Union{ .foo = {} }); } // union +comptime { _ = @max(0, struct { fn func() u8 { return 42; }}.func); } +comptime { _ = @max(0, .foo); } // enum literal + +const Struct = struct {}; +const Enum = enum { foo }; +const Union = union { foo: void }; // error // backend=stage2 // target=native // -// :2:17: error: expected number, found 'bool' +// :2:24: error: expected number, found 'type' +// :3:24: error: expected number, found 'void' +// :4:24: error: expected number, found 'bool' +// :5:24: error: expected number, found '*const u8' +// :6:29: error: expected number, found '[0]u8' +// :7:30: error: expected number, found 'tmp.Struct' +// :17:16: note: struct declared here +// :8:24: error: expected number, found '@TypeOf(null)' +// :9:24: error: expected number, found '?u8' +// :10:24: error: expected number, found 'error{}!u8' +// :11:24: error: expected number, found 'error{Foo}' +// :12:28: error: expected number, found 'tmp.Enum' +// :18:14: note: enum declared here +// :13:29: error: expected number, found 'tmp.Union' +// :19:15: note: union declared here +// :14:61: error: expected number, found 'fn () u8' +// :15:25: error: expected number, found '@Type(.enum_literal)'