authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-20 23:21:52+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-29 11:32:13-07:00
loge2837fd2245c213c842617d6d98e311057893bb0
treee42c8accf30a118fdb63f0c5302dd89d9f905f8d
parent46e724ab28ba5934471d8b2dec60acdd7885d64b

Sema: return comptime_int if all args to @min/@max are comptime_int

Resolves: #15776

2 files changed, 26 insertions(+), 1 deletions(-)

src/Sema.zig+9-1
...@@ -21940,10 +21940,18 @@ fn analyzeMinMax(...@@ -21940,10 +21940,18 @@ fn analyzeMinMax(
21940 }21940 }
21941 }21941 }
2194221942
21943 const opt_runtime_idx = runtime_known.findFirstSet();
21944
21943 const comptime_refined_ty: ?Type = if (cur_minmax) |ct_minmax_ref| refined: {21945 const comptime_refined_ty: ?Type = if (cur_minmax) |ct_minmax_ref| refined: {
21944 // Refine the comptime-known result type based on the operation21946 // Refine the comptime-known result type based on the operation
21945 const val = (try sema.resolveMaybeUndefVal(ct_minmax_ref)).?;21947 const val = (try sema.resolveMaybeUndefVal(ct_minmax_ref)).?;
21946 const orig_ty = sema.typeOf(ct_minmax_ref);21948 const orig_ty = sema.typeOf(ct_minmax_ref);
21949
21950 if (opt_runtime_idx == null and orig_ty.eql(Type.comptime_int, mod)) {
21951 // If all arguments were `comptime_int`, and there are no runtime args, we'll preserve that type
21952 break :refined orig_ty;
21953 }
21954
21947 const refined_ty = if (orig_ty.zigTypeTag() == .Vector) blk: {21955 const refined_ty = if (orig_ty.zigTypeTag() == .Vector) blk: {
21948 const elem_ty = orig_ty.childType();21956 const elem_ty = orig_ty.childType();
21949 const len = orig_ty.vectorLen();21957 const len = orig_ty.vectorLen();
...@@ -21982,7 +21990,7 @@ fn analyzeMinMax(...@@ -21982,7 +21990,7 @@ fn analyzeMinMax(
21982 break :refined refined_ty;21990 break :refined refined_ty;
21983 } else null;21991 } else null;
2198421992
21985 const runtime_idx = runtime_known.findFirstSet() orelse return cur_minmax.?;21993 const runtime_idx = opt_runtime_idx orelse return cur_minmax.?;
21986 const runtime_src = operand_srcs[runtime_idx];21994 const runtime_src = operand_srcs[runtime_idx];
21987 try sema.requireRuntimeBlock(block, src, runtime_src);21995 try sema.requireRuntimeBlock(block, src, runtime_src);
2198821996
test/behavior/maximum_minimum.zig+17
...@@ -194,3 +194,20 @@ test "@min/@max notices vector bounds" {...@@ -194,3 +194,20 @@ test "@min/@max notices vector bounds" {
194 try expectEqual(@Vector(2, u32){ 140, 300 }, max);194 try expectEqual(@Vector(2, u32){ 140, 300 }, max);
195 try expectEqual(@Vector(2, u32), @TypeOf(max));195 try expectEqual(@Vector(2, u32), @TypeOf(max));
196}196}
197
198test "@min/@max on comptime_int" {
199 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
200 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
205
206 const min = @min(1, 2, -2, -1);
207 const max = @max(1, 2, -2, -1);
208
209 try expectEqual(comptime_int, @TypeOf(min));
210 try expectEqual(comptime_int, @TypeOf(max));
211 try expectEqual(-2, min);
212 try expectEqual(2, max);
213}