Skip to content

Commit 2c0aa1c

Browse files
xdBronchmlugg
authored andcommitted
don't make anonymous tuple fields referencing comptime vars comptime
1 parent 27aba2d commit 2c0aa1c

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/Sema.zig

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20048,10 +20048,14 @@ fn arrayInitAnon(
2004820048
const types = try sema.arena.alloc(InternPool.Index, operands.len);
2004920049
const values = try sema.arena.alloc(InternPool.Index, operands.len);
2005020050

20051+
var any_comptime = false;
2005120052
const opt_runtime_src = rs: {
2005220053
var runtime_src: ?LazySrcLoc = null;
2005320054
for (operands, 0..) |operand, i| {
20054-
const operand_src = src; // TODO better source location
20055+
const operand_src = block.src(.{ .init_elem = .{
20056+
.init_node_offset = src.offset.node_offset.x,
20057+
.elem_index = @intCast(i),
20058+
} });
2005520059
const elem = try sema.resolveInst(operand);
2005620060
types[i] = sema.typeOf(elem).toIntern();
2005720061
if (Type.fromInterned(types[i]).zigTypeTag(zcu) == .@"opaque") {
@@ -20066,6 +20070,7 @@ fn arrayInitAnon(
2006620070
}
2006720071
if (try sema.resolveValue(elem)) |val| {
2006820072
values[i] = val.toIntern();
20073+
any_comptime = true;
2006920074
} else {
2007020075
values[i] = .none;
2007120076
runtime_src = operand_src;
@@ -20074,9 +20079,21 @@ fn arrayInitAnon(
2007420079
break :rs runtime_src;
2007520080
};
2007620081

20082+
// A field can't be `comptime` if it references a `comptime var` but the aggregate can still be comptime-known.
20083+
// Replace these fields with `.none` only for generating the type.
20084+
const values_no_comptime = if (!any_comptime) values else blk: {
20085+
const new_values = try sema.arena.alloc(InternPool.Index, operands.len);
20086+
for (values, new_values) |val, *new_val| {
20087+
if (val != .none and Value.fromInterned(val).canMutateComptimeVarState(zcu)) {
20088+
new_val.* = .none;
20089+
} else new_val.* = val;
20090+
}
20091+
break :blk new_values;
20092+
};
20093+
2007720094
const tuple_ty: Type = .fromInterned(try ip.getTupleType(gpa, pt.tid, .{
2007820095
.types = types,
20079-
.values = values,
20096+
.values = values_no_comptime,
2008020097
}));
2008120098

2008220099
const runtime_src = opt_runtime_src orelse {
@@ -20086,6 +20103,14 @@ fn arrayInitAnon(
2008620103

2008720104
try sema.requireRuntimeBlock(block, src, runtime_src);
2008820105

20106+
for (operands, 0..) |operand, i| {
20107+
const operand_src = block.src(.{ .init_elem = .{
20108+
.init_node_offset = src.offset.node_offset.x,
20109+
.elem_index = @intCast(i),
20110+
} });
20111+
try sema.validateRuntimeValue(block, operand_src, try sema.resolveInst(operand));
20112+
}
20113+
2008920114
if (is_ref) {
2009020115
const target = sema.pt.zcu.getTarget();
2009120116
const alloc_ty = try pt.ptrTypeSema(.{

test/behavior/tuple.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,15 @@ test "tuple with comptime fields with non empty initializer" {
486486
_ = a;
487487
}
488488

489+
test "anon tuple field referencing comptime var isn't comptime" {
490+
comptime var a: u8 = 0;
491+
const tuple = .{&a};
492+
// field isn't comptime but tuple is still comptime-known
493+
comptime assert(@TypeOf(tuple) == struct { *u8 });
494+
a = 1;
495+
comptime assert(tuple[0].* == 1);
496+
}
497+
489498
test "tuple with runtime value coerced into a slice with a sentinel" {
490499
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
491500
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

0 commit comments

Comments
 (0)