Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8050,6 +8050,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
const tracy = trace(@src());
defer tracy.end();

const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;

const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node });
Expand All @@ -8061,7 +8065,11 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
const uncasted_sentinel = try sema.resolveInst(extra.sentinel);
const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src);
const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel });
const array_ty = try sema.pt.arrayType(.{
if (sentinel_val.canMutateComptimeVarState(zcu)) {
const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);
return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val);
}
const array_ty = try pt.arrayType(.{
.len = len,
.sentinel = sentinel_val.toIntern(),
.child = elem_type.toIntern(),
Expand Down Expand Up @@ -19021,6 +19029,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air

const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;

const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
const elem_ty_src = block.src(.{ .node_offset_ptr_elem = extra.data.src_node });
Expand Down Expand Up @@ -19055,6 +19065,10 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src);
const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel });
try checkSentinelType(sema, block, sentinel_src, elem_ty);
if (val.canMutateComptimeVarState(zcu)) {
const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);
return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val);
}
break :blk val.toIntern();
} else .none;

Expand Down Expand Up @@ -20580,6 +20594,10 @@ fn zirReify(
const ptr_ty = try pt.singleMutPtrType(elem_ty);
const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
try sema.checkSentinelType(block, src, elem_ty);
if (sent_val.canMutateComptimeVarState(zcu)) {
const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sent_val);
}
break :s sent_val.toIntern();
}
break :s .none;
Expand Down Expand Up @@ -20645,7 +20663,12 @@ fn zirReify(
const sentinel = if (sentinel_val.optionalValue(zcu)) |p| blk: {
const ptr_ty = try pt.singleMutPtrType(child_ty);
try sema.checkSentinelType(block, src, child_ty);
break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
const sentinel = (try sema.pointerDeref(block, src, p, ptr_ty)).?;
if (sentinel.canMutateComptimeVarState(zcu)) {
const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sentinel);
}
break :blk sentinel;
} else null;

const ty = try pt.arrayType(.{
Expand Down Expand Up @@ -21387,6 +21410,9 @@ fn reifyTuple(
src,
.{ .simple = .tuple_field_default_value },
);
if (val.canMutateComptimeVarState(zcu)) {
return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
}
// Resolve the value so that lazy values do not create distinct types.
break :d (try sema.resolveLazyValue(val)).toIntern();
} else .none;
Expand Down Expand Up @@ -21500,6 +21526,9 @@ fn reifyStruct(
src,
.{ .simple = .struct_field_default_value },
);
if (val.canMutateComptimeVarState(zcu)) {
return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
}
// Resolve the value so that lazy values do not create distinct types.
break :d (try sema.resolveLazyValue(val)).toIntern();
} else .none;
Expand Down
2 changes: 1 addition & 1 deletion src/Zcu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2023,7 +2023,7 @@ pub const SrcLoc = struct {
},
.tuple_field_type, .tuple_field_init => |field_info| {
const tree = try src_loc.file_scope.getTree(zcu);
const node = src_loc.base_node;
const node = field_info.tuple_decl_node_offset.toAbsolute(src_loc.base_node);
var buf: [2]Ast.Node.Index = undefined;
const container_decl = tree.fullContainerDecl(&buf, node) orelse
return tree.nodeToSpan(node);
Expand Down
50 changes: 50 additions & 0 deletions test/cases/default_value_references_comptime_var.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export fn foo() void {
comptime var a: u8 = 0;
_ = struct { comptime *u8 = &a };
}
export fn bar() void {
comptime var a: u8 = 0;
_ = @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &.{.{
.name = "0",
.type = *u8,
.default_value_ptr = @ptrCast(&&a),
.is_comptime = true,
.alignment = @alignOf(*u8),
}},
.decls = &.{},
.is_tuple = true,
} });
}

export fn baz() void {
comptime var a: u8 = 0;
_ = struct { foo: *u8 = &a };
}
export fn qux() void {
comptime var a: u8 = 0;
_ = @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &.{.{
.name = "foo",
.type = *u8,
.default_value_ptr = @ptrCast(&&a),
.is_comptime = false,
.alignment = @alignOf(*u8),
}},
.decls = &.{},
.is_tuple = false,
} });
}

// error
//
// :3:33: error: field default value contains reference to comptime var
// :2:14: note: '0' points to comptime var declared here
// :7:9: error: field default value contains reference to comptime var
// :6:14: note: '0' points to comptime var declared here
// :23:9: error: captured value contains reference to comptime var
// :22:14: note: 'a' points to comptime var declared here
// :27:9: error: field default value contains reference to comptime var
// :26:14: note: 'foo' points to comptime var declared here
41 changes: 41 additions & 0 deletions test/cases/sentinel_references_comptime_var.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export fn foo() void {
comptime var a: u8 = 0;
_ = [0:&a]*u8;
}
export fn bar() void {
comptime var a: u8 = 0;
_ = @Type(.{ .array = .{
.child = *u8,
.len = 0,
.sentinel_ptr = @ptrCast(&&a),
} });
}

export fn baz() void {
comptime var a: u8 = 0;
_ = [:&a]*u8;
}
export fn qux() void {
comptime var a: u8 = 0;
_ = @Type(.{ .pointer = .{
.size = .many,
.is_const = false,
.is_volatile = false,
.alignment = @alignOf(u8),
.address_space = .generic,
.child = *u8,
.is_allowzero = false,
.sentinel_ptr = @ptrCast(&&a),
} });
}

// error
//
// :3:12: error: sentinel contains reference to comptime var
// :2:14: note: 'sentinel' points to comptime var declared here
// :7:9: error: sentinel contains reference to comptime var
// :6:14: note: 'sentinel_ptr' points to comptime var declared here
// :16:11: error: sentinel contains reference to comptime var
// :15:14: note: 'sentinel' points to comptime var declared here
// :20:9: error: sentinel contains reference to comptime var
// :19:14: note: 'sentinel_ptr' points to comptime var declared here