Skip to content

Commit 2810e4b

Browse files
xdBronchmlugg
authored andcommitted
detect references to comptime var in default values and sentinels
1 parent 6893e7f commit 2810e4b

File tree

4 files changed

+123
-3
lines changed

4 files changed

+123
-3
lines changed

src/Sema.zig

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8050,6 +8050,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
80508050
const tracy = trace(@src());
80518051
defer tracy.end();
80528052

8053+
const pt = sema.pt;
8054+
const zcu = pt.zcu;
8055+
const ip = &zcu.intern_pool;
8056+
80538057
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
80548058
const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
80558059
const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node });
@@ -8061,7 +8065,11 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
80618065
const uncasted_sentinel = try sema.resolveInst(extra.sentinel);
80628066
const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src);
80638067
const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel });
8064-
const array_ty = try sema.pt.arrayType(.{
8068+
if (sentinel_val.canMutateComptimeVarState(zcu)) {
8069+
const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);
8070+
return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val);
8071+
}
8072+
const array_ty = try pt.arrayType(.{
80658073
.len = len,
80668074
.sentinel = sentinel_val.toIntern(),
80678075
.child = elem_type.toIntern(),
@@ -19021,6 +19029,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1902119029

1902219030
const pt = sema.pt;
1902319031
const zcu = pt.zcu;
19032+
const ip = &zcu.intern_pool;
19033+
1902419034
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
1902519035
const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
1902619036
const elem_ty_src = block.src(.{ .node_offset_ptr_elem = extra.data.src_node });
@@ -19055,6 +19065,10 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1905519065
const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src);
1905619066
const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel });
1905719067
try checkSentinelType(sema, block, sentinel_src, elem_ty);
19068+
if (val.canMutateComptimeVarState(zcu)) {
19069+
const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);
19070+
return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val);
19071+
}
1905819072
break :blk val.toIntern();
1905919073
} else .none;
1906019074

@@ -20580,6 +20594,10 @@ fn zirReify(
2058020594
const ptr_ty = try pt.singleMutPtrType(elem_ty);
2058120595
const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
2058220596
try sema.checkSentinelType(block, src, elem_ty);
20597+
if (sent_val.canMutateComptimeVarState(zcu)) {
20598+
const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20599+
return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sent_val);
20600+
}
2058320601
break :s sent_val.toIntern();
2058420602
}
2058520603
break :s .none;
@@ -20645,7 +20663,12 @@ fn zirReify(
2064520663
const sentinel = if (sentinel_val.optionalValue(zcu)) |p| blk: {
2064620664
const ptr_ty = try pt.singleMutPtrType(child_ty);
2064720665
try sema.checkSentinelType(block, src, child_ty);
20648-
break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
20666+
const sentinel = (try sema.pointerDeref(block, src, p, ptr_ty)).?;
20667+
if (sentinel.canMutateComptimeVarState(zcu)) {
20668+
const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20669+
return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sentinel);
20670+
}
20671+
break :blk sentinel;
2064920672
} else null;
2065020673

2065120674
const ty = try pt.arrayType(.{
@@ -21387,6 +21410,9 @@ fn reifyTuple(
2138721410
src,
2138821411
.{ .simple = .tuple_field_default_value },
2138921412
);
21413+
if (val.canMutateComptimeVarState(zcu)) {
21414+
return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21415+
}
2139021416
// Resolve the value so that lazy values do not create distinct types.
2139121417
break :d (try sema.resolveLazyValue(val)).toIntern();
2139221418
} else .none;
@@ -21500,6 +21526,9 @@ fn reifyStruct(
2150021526
src,
2150121527
.{ .simple = .struct_field_default_value },
2150221528
);
21529+
if (val.canMutateComptimeVarState(zcu)) {
21530+
return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21531+
}
2150321532
// Resolve the value so that lazy values do not create distinct types.
2150421533
break :d (try sema.resolveLazyValue(val)).toIntern();
2150521534
} else .none;

src/Zcu.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2023,7 +2023,7 @@ pub const SrcLoc = struct {
20232023
},
20242024
.tuple_field_type, .tuple_field_init => |field_info| {
20252025
const tree = try src_loc.file_scope.getTree(zcu);
2026-
const node = src_loc.base_node;
2026+
const node = field_info.tuple_decl_node_offset.toAbsolute(src_loc.base_node);
20272027
var buf: [2]Ast.Node.Index = undefined;
20282028
const container_decl = tree.fullContainerDecl(&buf, node) orelse
20292029
return tree.nodeToSpan(node);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export fn foo() void {
2+
comptime var a: u8 = 0;
3+
_ = struct { comptime *u8 = &a };
4+
}
5+
export fn bar() void {
6+
comptime var a: u8 = 0;
7+
_ = @Type(.{ .@"struct" = .{
8+
.layout = .auto,
9+
.fields = &.{.{
10+
.name = "0",
11+
.type = *u8,
12+
.default_value_ptr = @ptrCast(&&a),
13+
.is_comptime = true,
14+
.alignment = @alignOf(*u8),
15+
}},
16+
.decls = &.{},
17+
.is_tuple = true,
18+
} });
19+
}
20+
21+
export fn baz() void {
22+
comptime var a: u8 = 0;
23+
_ = struct { foo: *u8 = &a };
24+
}
25+
export fn qux() void {
26+
comptime var a: u8 = 0;
27+
_ = @Type(.{ .@"struct" = .{
28+
.layout = .auto,
29+
.fields = &.{.{
30+
.name = "foo",
31+
.type = *u8,
32+
.default_value_ptr = @ptrCast(&&a),
33+
.is_comptime = false,
34+
.alignment = @alignOf(*u8),
35+
}},
36+
.decls = &.{},
37+
.is_tuple = false,
38+
} });
39+
}
40+
41+
// error
42+
//
43+
// :3:33: error: field default value contains reference to comptime var
44+
// :2:14: note: '0' points to comptime var declared here
45+
// :7:9: error: field default value contains reference to comptime var
46+
// :6:14: note: '0' points to comptime var declared here
47+
// :23:9: error: captured value contains reference to comptime var
48+
// :22:14: note: 'a' points to comptime var declared here
49+
// :27:9: error: field default value contains reference to comptime var
50+
// :26:14: note: 'foo' points to comptime var declared here
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export fn foo() void {
2+
comptime var a: u8 = 0;
3+
_ = [0:&a]*u8;
4+
}
5+
export fn bar() void {
6+
comptime var a: u8 = 0;
7+
_ = @Type(.{ .array = .{
8+
.child = *u8,
9+
.len = 0,
10+
.sentinel_ptr = @ptrCast(&&a),
11+
} });
12+
}
13+
14+
export fn baz() void {
15+
comptime var a: u8 = 0;
16+
_ = [:&a]*u8;
17+
}
18+
export fn qux() void {
19+
comptime var a: u8 = 0;
20+
_ = @Type(.{ .pointer = .{
21+
.size = .many,
22+
.is_const = false,
23+
.is_volatile = false,
24+
.alignment = @alignOf(u8),
25+
.address_space = .generic,
26+
.child = *u8,
27+
.is_allowzero = false,
28+
.sentinel_ptr = @ptrCast(&&a),
29+
} });
30+
}
31+
32+
// error
33+
//
34+
// :3:12: error: sentinel contains reference to comptime var
35+
// :2:14: note: 'sentinel' points to comptime var declared here
36+
// :7:9: error: sentinel contains reference to comptime var
37+
// :6:14: note: 'sentinel_ptr' points to comptime var declared here
38+
// :16:11: error: sentinel contains reference to comptime var
39+
// :15:14: note: 'sentinel' points to comptime var declared here
40+
// :20:9: error: sentinel contains reference to comptime var
41+
// :19:14: note: 'sentinel_ptr' points to comptime var declared here

0 commit comments

Comments
 (0)