diff --git a/src/Sema.zig b/src/Sema.zig index a960980eec00ed4a5af9d8b6ce2e35c42c0f5dee..ba56bb659458bae131451fd40a8bb9923cb8aaef 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -34258,9 +34258,15 @@ const DerefResult = union(enum) { fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value) CompileError!DerefResult { const pt = sema.pt; - const ip = &pt.zcu.intern_pool; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; switch (try sema.loadComptimePtr(block, src, ptr_val)) { - .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) }, + .success => |mv| { + const loaded_val = try mv.intern(pt, sema.arena); + const elem_ty_ip = ptr_val.typeOf(zcu).ptrInfo(zcu).child; + assert(loaded_val.typeOf(zcu).toIntern() == elem_ty_ip); + return .{ .val = loaded_val }; + }, .runtime_load => return .runtime_load, .undef => return sema.failWithUseOfUndef(block, src, null), .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}), diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index bc56aed0818a8dd405d5935a5229ddfbaa2c4d50..96d407f9ffb2fe271fa4f1325343928bbb700d97 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -377,8 +377,15 @@ fn loadComptimePtrInner( src, null, )) { - // We already have a value which is IMC to the desired type. - return .{ .success = base_val }; + // We already have a value which is IMC to the desired type. If the type matches + // exactly we can just return `base_val`, otherwise we need to do the coercion. + if (base_val.typeOf(zcu).toIntern() == load_ty.toIntern()) { + return .{ .success = base_val }; + } else { + const interned_val = try base_val.intern(pt, sema.arena); + const coerced_val = try pt.getCoerced(interned_val, load_ty); + return .{ .success = .{ .interned = coerced_val.toIntern() } }; + } } } } diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig index 979e6a3752e533596d7f1c5bb1a5af4e33a40b49..75bbca0a12b98ce34454281b17f07c0d59c9ffba 100644 --- a/test/behavior/comptime_memory.zig +++ b/test/behavior/comptime_memory.zig @@ -1,7 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); const endian = builtin.cpu.arch.endian(); -const testing = @import("std").testing; +const testing = std.testing; +const assert = std.debug.assert; const ptr_size = @sizeOf(usize); test "type pun signed and unsigned as single pointer" { @@ -605,3 +606,13 @@ test "reinterpret sentinel-terminated array as packed struct" { }, } } + +test "reinterpret pointer as optional pointer via double-pointer coercion" { + const p0: *const *anyopaque = &@ptrFromInt(0x1000); + const p1: *const ?*anyopaque = p0; + + const loaded = p1.*; + + comptime assert(@TypeOf(loaded) == ?*anyopaque); + comptime assert(@intFromPtr(loaded) == 0x1000); +}