Skip to content

Commit 4303b43

Browse files
authored
Merge pull request #22907 from MasonRemaley/import-zon-anon-type
Allow importing ZON without a result type (you can import build.zig.zon now)
2 parents bfab958 + dd3f01e commit 4303b43

15 files changed

+329
-37
lines changed

src/InternPool.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,7 @@ pub const Key = union(enum) {
21362136
/// To avoid making this key overly complex, the type-specific data is hashed by Sema.
21372137
reified: struct {
21382138
/// A `reify`, `struct_init`, `struct_init_ref`, or `struct_init_anon` instruction.
2139+
/// Alternatively, this is `main_struct_inst` of a ZON file.
21392140
zir_index: TrackedInst.Index,
21402141
/// A hash of this type's attributes, fields, etc, generated by Sema.
21412142
type_hash: u64,

src/Sema.zig

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2998,7 +2998,7 @@ fn zirStructDecl(
29982998
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
29992999
}
30003000

3001-
fn createTypeName(
3001+
pub fn createTypeName(
30023002
sema: *Sema,
30033003
block: *Block,
30043004
name_strategy: Zir.Inst.NameStrategy,
@@ -14065,14 +14065,13 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1406514065
return Air.internedToRef(ty);
1406614066
},
1406714067
.zon => {
14068-
if (extra.res_ty == .none) {
14069-
return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{});
14070-
}
14071-
const res_ty_inst = try sema.resolveInst(extra.res_ty);
14072-
const res_ty = try sema.analyzeAsType(block, operand_src, res_ty_inst);
14073-
if (res_ty.isGenericPoison()) {
14074-
return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{});
14075-
}
14068+
const res_ty: InternPool.Index = b: {
14069+
if (extra.res_ty == .none) break :b .none;
14070+
const res_ty_inst = try sema.resolveInst(extra.res_ty);
14071+
const res_ty = try sema.analyzeAsType(block, operand_src, res_ty_inst);
14072+
if (res_ty.isGenericPoison()) break :b .none;
14073+
break :b res_ty.toIntern();
14074+
};
1407614075

1407714076
try sema.declareDependency(.{ .zon_file = result.file_index });
1407814077
const interned = try LowerZon.run(
@@ -31699,7 +31698,7 @@ fn addReferenceEntry(
3169931698
try zcu.addUnitReference(sema.owner, referenced_unit, src);
3170031699
}
3170131700

31702-
fn addTypeReferenceEntry(
31701+
pub fn addTypeReferenceEntry(
3170331702
sema: *Sema,
3170431703
src: LazySrcLoc,
3170531704
referenced_type: InternPool.Index,

src/Sema/LowerZon.zig

Lines changed: 170 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn run(
3333
sema: *Sema,
3434
file: *File,
3535
file_index: Zcu.File.Index,
36-
res_ty: Type,
36+
res_ty_interned: InternPool.Index,
3737
import_loc: LazySrcLoc,
3838
block: *Sema.Block,
3939
) CompileError!InternPool.Index {
@@ -53,13 +53,167 @@ pub fn run(
5353
.base_node_inst = tracked_inst,
5454
};
5555

56-
try lower_zon.checkType(res_ty);
56+
if (res_ty_interned == .none) {
57+
return lower_zon.lowerExprAnonResTy(.root);
58+
} else {
59+
const res_ty: Type = .fromInterned(res_ty_interned);
60+
try lower_zon.checkType(res_ty);
61+
return lower_zon.lowerExprKnownResTy(.root, res_ty);
62+
}
63+
}
5764

58-
return lower_zon.lowerExpr(.root, res_ty);
65+
fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index {
66+
const gpa = self.sema.gpa;
67+
const pt = self.sema.pt;
68+
const ip = &pt.zcu.intern_pool;
69+
switch (node.get(self.file.zoir.?)) {
70+
.true => return .bool_true,
71+
.false => return .bool_false,
72+
.null => return .null_value,
73+
.pos_inf => return self.fail(node, "infinity requires a known result type", .{}),
74+
.neg_inf => return self.fail(node, "negative infinity requires a known result type", .{}),
75+
.nan => return self.fail(node, "NaN requires a known result type", .{}),
76+
.int_literal => |int| switch (int) {
77+
.small => |val| return pt.intern(.{ .int = .{
78+
.ty = .comptime_int_type,
79+
.storage = .{ .i64 = val },
80+
} }),
81+
.big => |val| return pt.intern(.{ .int = .{
82+
.ty = .comptime_int_type,
83+
.storage = .{ .big_int = val },
84+
} }),
85+
},
86+
.float_literal => |val| {
87+
const result = try pt.floatValue(.comptime_float, val);
88+
return result.toIntern();
89+
},
90+
.char_literal => |val| return pt.intern(.{ .int = .{
91+
.ty = .comptime_int_type,
92+
.storage = .{ .i64 = val },
93+
} }),
94+
.enum_literal => |val| return pt.intern(.{
95+
.enum_literal = try ip.getOrPutString(
96+
gpa,
97+
pt.tid,
98+
val.get(self.file.zoir.?),
99+
.no_embedded_nulls,
100+
),
101+
}),
102+
.string_literal => |val| {
103+
const ip_str = try ip.getOrPutString(gpa, pt.tid, val, .maybe_embedded_nulls);
104+
const result = try self.sema.addStrLit(ip_str, val.len);
105+
return result.toInterned().?;
106+
},
107+
.empty_literal => return .empty_tuple,
108+
.array_literal => |nodes| {
109+
const types = try self.sema.arena.alloc(InternPool.Index, nodes.len);
110+
const values = try self.sema.arena.alloc(InternPool.Index, nodes.len);
111+
for (0..nodes.len) |i| {
112+
values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i)));
113+
types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern();
114+
}
115+
const ty = try ip.getTupleType(
116+
gpa,
117+
pt.tid,
118+
.{
119+
.types = types,
120+
.values = values,
121+
},
122+
);
123+
return pt.intern(.{ .aggregate = .{
124+
.ty = ty,
125+
.storage = .{ .elems = values },
126+
} });
127+
},
128+
.struct_literal => |init| {
129+
const elems = try self.sema.arena.alloc(InternPool.Index, init.names.len);
130+
for (0..init.names.len) |i| {
131+
elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i)));
132+
}
133+
const struct_ty = switch (try ip.getStructType(
134+
gpa,
135+
pt.tid,
136+
.{
137+
.layout = .auto,
138+
.fields_len = @intCast(init.names.len),
139+
.known_non_opv = false,
140+
.requires_comptime = .no,
141+
.any_comptime_fields = true,
142+
.any_default_inits = true,
143+
.inits_resolved = true,
144+
.any_aligned_fields = false,
145+
.key = .{ .reified = .{
146+
.zir_index = self.base_node_inst,
147+
.type_hash = hash: {
148+
var hasher: std.hash.Wyhash = .init(0);
149+
hasher.update(std.mem.asBytes(&node));
150+
hasher.update(std.mem.sliceAsBytes(elems));
151+
hasher.update(std.mem.sliceAsBytes(init.names));
152+
break :hash hasher.final();
153+
},
154+
} },
155+
},
156+
false,
157+
)) {
158+
.wip => |wip| ty: {
159+
errdefer wip.cancel(ip, pt.tid);
160+
wip.setName(ip, try self.sema.createTypeName(
161+
self.block,
162+
.anon,
163+
"struct",
164+
self.base_node_inst.resolve(ip),
165+
wip.index,
166+
));
167+
168+
const struct_type = ip.loadStructType(wip.index);
169+
170+
for (init.names, 0..) |name, field_idx| {
171+
const name_interned = try ip.getOrPutString(
172+
gpa,
173+
pt.tid,
174+
name.get(self.file.zoir.?),
175+
.no_embedded_nulls,
176+
);
177+
assert(struct_type.addFieldName(ip, name_interned) == null);
178+
struct_type.setFieldComptime(ip, field_idx);
179+
}
180+
181+
@memcpy(struct_type.field_inits.get(ip), elems);
182+
const types = struct_type.field_types.get(ip);
183+
for (0..init.names.len) |i| {
184+
types[i] = Value.fromInterned(elems[i]).typeOf(pt.zcu).toIntern();
185+
}
186+
187+
const new_namespace_index = try pt.createNamespace(.{
188+
.parent = self.block.namespace.toOptional(),
189+
.owner_type = wip.index,
190+
.file_scope = self.block.getFileScopeIndex(pt.zcu),
191+
.generation = pt.zcu.generation,
192+
});
193+
try pt.zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
194+
codegen_type: {
195+
if (pt.zcu.comp.config.use_llvm) break :codegen_type;
196+
if (self.block.ownerModule().strip) break :codegen_type;
197+
try pt.zcu.comp.queueJob(.{ .codegen_type = wip.index });
198+
}
199+
break :ty wip.finish(ip, new_namespace_index);
200+
},
201+
.existing => |ty| ty,
202+
};
203+
try self.sema.declareDependency(.{ .interned = struct_ty });
204+
try self.sema.addTypeReferenceEntry(self.nodeSrc(node), struct_ty);
205+
206+
return try pt.intern(.{ .aggregate = .{
207+
.ty = struct_ty,
208+
.storage = .{ .elems = elems },
209+
} });
210+
},
211+
}
59212
}
60213

61-
/// Validate that `ty` is a valid ZON type. If not, emit a compile error.
62-
/// i.e. no nested optionals, no error sets, etc.
214+
/// Validate that `ty` is a valid ZON type, or emit a compile error.
215+
///
216+
/// Rules out nested optionals, error sets, etc.
63217
fn checkType(self: *LowerZon, ty: Type) !void {
64218
var visited: std.AutoHashMapUnmanaged(InternPool.Index, void) = .empty;
65219
try self.checkTypeInner(ty, null, &visited);
@@ -201,9 +355,9 @@ fn fail(
201355
return self.sema.failWithOwnedErrorMsg(self.block, err_msg);
202356
}
203357

204-
fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index {
358+
fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index {
205359
const pt = self.sema.pt;
206-
return self.lowerExprInner(node, res_ty) catch |err| switch (err) {
360+
return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {
207361
error.WrongType => return self.fail(
208362
node,
209363
"expected type '{}'",
@@ -213,7 +367,7 @@ fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!
213367
};
214368
}
215369

216-
fn lowerExprInner(
370+
fn lowerExprKnownResTyInner(
217371
self: *LowerZon,
218372
node: Zoir.Node.Index,
219373
res_ty: Type,
@@ -227,7 +381,7 @@ fn lowerExprInner(
227381
break :b .none;
228382
} else b: {
229383
const child_type = res_ty.optionalChild(pt.zcu);
230-
break :b try self.lowerExprInner(node, child_type);
384+
break :b try self.lowerExprKnownResTyInner(node, child_type);
231385
},
232386
},
233387
}),
@@ -239,7 +393,7 @@ fn lowerExprInner(
239393
.base_addr = .{
240394
.uav = .{
241395
.orig_ty = res_ty.toIntern(),
242-
.val = try self.lowerExprInner(node, .fromInterned(ptr_info.child)),
396+
.val = try self.lowerExprKnownResTyInner(node, .fromInterned(ptr_info.child)),
243397
},
244398
},
245399
.byte_offset = 0,
@@ -486,7 +640,7 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
486640
);
487641

488642
for (0..nodes.len) |i| {
489-
elems[i] = try self.lowerExpr(nodes.at(@intCast(i)), array_info.elem_type);
643+
elems[i] = try self.lowerExprKnownResTy(nodes.at(@intCast(i)), array_info.elem_type);
490644
}
491645

492646
if (array_info.sentinel) |sentinel| {
@@ -587,7 +741,7 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
587741
);
588742
}
589743

590-
const val = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(field_types[i]));
744+
const val = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(field_types[i]));
591745

592746
if (elems[i] != .none and val != elems[i]) {
593747
const elem_node = elem_nodes.at(@intCast(i));
@@ -650,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
650804
};
651805

652806
const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);
653-
field_values[name_index] = try self.lowerExpr(field_node, field_type);
807+
field_values[name_index] = try self.lowerExprKnownResTy(field_node, field_type);
654808

655809
if (struct_info.comptime_bits.getBit(ip, name_index)) {
656810
const val = ip.indexToKey(field_values[name_index]);
@@ -715,7 +869,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
715869
const elems = try self.sema.arena.alloc(InternPool.Index, elem_nodes.len + @intFromBool(ptr_info.sentinel != .none));
716870

717871
for (elems, 0..) |*elem, i| {
718-
elem.* = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(ptr_info.child));
872+
elem.* = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(ptr_info.child));
719873
}
720874

721875
if (ptr_info.sentinel != .none) {
@@ -810,7 +964,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
810964
if (field_type.toIntern() == .void_type) {
811965
return self.fail(field_node, "expected type 'void'", .{});
812966
}
813-
break :b try self.lowerExpr(field_node, field_type);
967+
break :b try self.lowerExprKnownResTy(field_node, field_type);
814968
} else b: {
815969
if (field_type.toIntern() != .void_type) {
816970
return error.WrongType;
@@ -846,7 +1000,7 @@ fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
8461000
}
8471001

8481002
for (elems, 0..) |*elem, i| {
849-
elem.* = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(vector_info.child));
1003+
elem.* = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(vector_info.child));
8501004
}
8511005

8521006
return self.sema.pt.intern(.{ .aggregate = .{

src/Type.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3589,7 +3589,10 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
35893589
};
35903590
const info = tracked.resolveFull(&zcu.intern_pool) orelse return null;
35913591
const file = zcu.fileByIndex(info.file);
3592-
const zir = file.zir.?;
3592+
const zir = switch (file.getMode()) {
3593+
.zig => file.zir.?,
3594+
.zon => return 0,
3595+
};
35933596
const inst = zir.instructions.get(@intFromEnum(info.inst));
35943597
return switch (inst.tag) {
35953598
.struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line,

src/Zcu.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2753,7 +2753,7 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir
27532753
},
27542754
.{
27552755
.base = @ptrCast(zoir.limbs),
2756-
.len = zoir.limbs.len * 4,
2756+
.len = zoir.limbs.len * @sizeOf(std.math.big.Limb),
27572757
},
27582758
.{
27592759
.base = zoir.string_bytes.ptr,

src/Zcu/PerThread.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ pub fn updateFile(
234234
error.FileTooBig => unreachable, // 0 is not too big
235235
else => |e| return e,
236236
};
237+
try cache_file.seekTo(0);
237238

238239
if (stat.size > std.math.maxInt(u32))
239240
return error.FileTooBig;

stage1/wasi.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,8 @@ uint32_t wasi_snapshot_preview1_fd_seek(uint32_t fd, uint64_t in_offset, uint32_
10031003
default: panic("unimplemented");
10041004
}
10051005

1006+
if (fds[fd].stream == NULL) return wasi_errno_success;
1007+
10061008
int seek_whence;
10071009
switch (whence) {
10081010
case wasi_whence_set:

0 commit comments

Comments
 (0)