From f244c8891a6956fb9560c26e516278052b5acef5 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 21 Jan 2025 22:04:16 +0000 Subject: [PATCH 1/4] std.mem.Allocator: remove redundant check This check doesn't make sense with the modern Allocator API; it's left over from when realloc could change alignment. It's statically known (but not comptime-known) to be true always. This check was one of the things blocking Allocator from being used at comptime (related: #1291). --- lib/std/mem/Allocator.zig | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig index c6b0369127..7cf201d4b1 100644 --- a/lib/std/mem/Allocator.zig +++ b/lib/std/mem/Allocator.zig @@ -282,11 +282,9 @@ pub fn reallocAdvanced( const old_byte_slice = mem.sliceAsBytes(old_mem); const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure - if (mem.isAligned(@intFromPtr(old_byte_slice.ptr), Slice.alignment)) { - if (self.rawResize(old_byte_slice, log2a(Slice.alignment), byte_count, return_address)) { - const new_bytes: []align(Slice.alignment) u8 = @alignCast(old_byte_slice.ptr[0..byte_count]); - return mem.bytesAsSlice(T, new_bytes); - } + if (self.rawResize(old_byte_slice, log2a(Slice.alignment), byte_count, return_address)) { + const new_bytes: []align(Slice.alignment) u8 = @alignCast(old_byte_slice.ptr[0..byte_count]); + return mem.bytesAsSlice(T, new_bytes); } const new_mem = self.rawAlloc(byte_count, log2a(Slice.alignment), return_address) orelse From 6e7ae66871575a2bf6b15c0f0280b13a57fc59eb Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 22 Jan 2025 02:02:19 +0000 Subject: [PATCH 2/4] std.debug: remove `errorReturnTraceHelper` This function doesn't do what it says; it's a nop. --- lib/std/debug.zig | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 38922a7655..9f66599aa0 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -413,16 +413,9 @@ pub fn assertReadable(slice: []const volatile u8) void { for (slice) |*byte| _ = byte.*; } -/// By including a call to this function, the caller gains an error return trace -/// secret parameter, making `@errorReturnTrace()` more useful. This is not -/// necessary if the function already contains a call to an errorable function -/// elsewhere. -pub fn errorReturnTraceHelper() anyerror!void {} - /// Equivalent to `@panic` but with a formatted message. pub fn panic(comptime format: []const u8, args: anytype) noreturn { @branchHint(.cold); - errorReturnTraceHelper() catch unreachable; panicExtra(@errorReturnTrace(), @returnAddress(), format, args); } From 8470b6ea37a82330be2c5ab41460fe58b8cfd4f6 Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 22 Jan 2025 02:22:39 +0000 Subject: [PATCH 3/4] Zcu: fix switch prong source location resolution Resolves: #22343 --- src/Zcu.zig | 5 +- .../compile_errors/invalid_switch_item.zig | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test/cases/compile_errors/invalid_switch_item.zig diff --git a/src/Zcu.zig b/src/Zcu.zig index 8f35253509..c75cd5d40c 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1864,15 +1864,16 @@ pub const SrcLoc = struct { if (want_case_idx.isSpecial()) { break case; } + continue; } const is_multi = case.ast.values.len != 1 or node_tags[case.ast.values[0]] == .switch_range; - if (!want_case_idx.isSpecial()) switch (want_case_idx.kind) { + switch (want_case_idx.kind) { .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case, .multi => if (is_multi and want_case_idx.index == multi_i) break case, - }; + } if (is_multi) { multi_i += 1; diff --git a/test/cases/compile_errors/invalid_switch_item.zig b/test/cases/compile_errors/invalid_switch_item.zig new file mode 100644 index 0000000000..ee8c2a8b36 --- /dev/null +++ b/test/cases/compile_errors/invalid_switch_item.zig @@ -0,0 +1,46 @@ +const E = enum { a, b, c }; +var my_e: E = .a; + +export fn f0() void { + switch (my_e) { + .a => {}, + .b => {}, + .x => {}, + .c => {}, + } +} + +export fn f1() void { + switch (my_e) { + else => {}, + .x, .y => {}, + } +} + +export fn f2() void { + switch (my_e) { + else => {}, + .a => {}, + .x, .y => {}, + .b => {}, + } +} + +export fn f3() void { + switch (my_e) { + .a, .b => {}, + .x, .y => {}, + else => {}, + } +} + +// error +// +// :8:10: error: no field named 'x' in enum 'tmp.E' +// :1:11: note: enum declared here +// :16:10: error: no field named 'x' in enum 'tmp.E' +// :1:11: note: enum declared here +// :24:10: error: no field named 'x' in enum 'tmp.E' +// :1:11: note: enum declared here +// :32:10: error: no field named 'x' in enum 'tmp.E' +// :1:11: note: enum declared here From e864c38cc38095a1496229803465fdd0d079f9c3 Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 22 Jan 2025 04:16:16 +0000 Subject: [PATCH 4/4] Sema: fix crash when `inline` loop condition is not comptime-known --- lib/std/zig.zig | 2 ++ src/Sema.zig | 9 ++++++++- .../runtime_condition_in_inline_loop.zig | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/runtime_condition_in_inline_loop.zig diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 6fec585326..4ebb95c522 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -788,6 +788,7 @@ pub const SimpleComptimeReason = enum(u32) { // Miscellaneous reasons. comptime_keyword, comptime_call_modifier, + inline_loop_operand, switch_item, tuple_field_default_value, struct_field_default_value, @@ -863,6 +864,7 @@ pub const SimpleComptimeReason = enum(u32) { .comptime_keyword => "'comptime' keyword forces comptime evaluation", .comptime_call_modifier => "'.compile_time' call modifier forces comptime evaluation", + .inline_loop_operand => "inline loop condition must be comptime-known", .switch_item => "switch prong values must be comptime-known", .tuple_field_default_value => "tuple field default value must be comptime-known", .struct_field_default_value => "struct field default value must be comptime-known", diff --git a/src/Sema.zig b/src/Sema.zig index 978396e371..fb9b27a8cd 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1824,7 +1824,14 @@ fn analyzeBodyInner( ); const uncasted_cond = try sema.resolveInst(extra.data.condition); const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src); - const cond_val = try sema.resolveConstDefinedValue(block, cond_src, cond, null); + const cond_val = try sema.resolveConstDefinedValue( + block, + cond_src, + cond, + // If this block is comptime, it's more helpful to just give the outer message. + // This is particularly true if this came from a comptime `condbr` above. + if (block.isComptime()) null else .{ .simple = .inline_loop_operand }, + ); const inline_body = if (cond_val.toBool()) then_body else else_body; try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); diff --git a/test/cases/compile_errors/runtime_condition_in_inline_loop.zig b/test/cases/compile_errors/runtime_condition_in_inline_loop.zig new file mode 100644 index 0000000000..65ed3d0367 --- /dev/null +++ b/test/cases/compile_errors/runtime_condition_in_inline_loop.zig @@ -0,0 +1,16 @@ +var rt_slice: []const u8 = &.{ 1, 2, 3 }; + +export fn foo() void { + inline for (rt_slice) |_| {} +} + +export fn bar() void { + inline while (rt_slice.len == 0) {} +} + +// error +// +// :4:17: error: unable to resolve comptime value +// :4:17: note: inline loop condition must be comptime-known +// :8:32: error: unable to resolve comptime value +// :8:32: note: inline loop condition must be comptime-known