@@ -33,7 +33,7 @@ pub fn run(
33
33
sema : * Sema ,
34
34
file : * File ,
35
35
file_index : Zcu.File.Index ,
36
- res_ty : Type ,
36
+ res_ty_interned : InternPool.Index ,
37
37
import_loc : LazySrcLoc ,
38
38
block : * Sema.Block ,
39
39
) CompileError ! InternPool.Index {
@@ -53,13 +53,167 @@ pub fn run(
53
53
.base_node_inst = tracked_inst ,
54
54
};
55
55
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
+ }
57
64
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
+ }
59
212
}
60
213
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.
63
217
fn checkType (self : * LowerZon , ty : Type ) ! void {
64
218
var visited : std .AutoHashMapUnmanaged (InternPool.Index , void ) = .empty ;
65
219
try self .checkTypeInner (ty , null , & visited );
@@ -201,9 +355,9 @@ fn fail(
201
355
return self .sema .failWithOwnedErrorMsg (self .block , err_msg );
202
356
}
203
357
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 {
205
359
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 ) {
207
361
error .WrongType = > return self .fail (
208
362
node ,
209
363
"expected type '{}'" ,
@@ -213,7 +367,7 @@ fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!
213
367
};
214
368
}
215
369
216
- fn lowerExprInner (
370
+ fn lowerExprKnownResTyInner (
217
371
self : * LowerZon ,
218
372
node : Zoir.Node.Index ,
219
373
res_ty : Type ,
@@ -227,7 +381,7 @@ fn lowerExprInner(
227
381
break :b .none ;
228
382
} else b : {
229
383
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 );
231
385
},
232
386
},
233
387
}),
@@ -239,7 +393,7 @@ fn lowerExprInner(
239
393
.base_addr = .{
240
394
.uav = .{
241
395
.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 )),
243
397
},
244
398
},
245
399
.byte_offset = 0 ,
@@ -486,7 +640,7 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
486
640
);
487
641
488
642
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 );
490
644
}
491
645
492
646
if (array_info .sentinel ) | sentinel | {
@@ -587,7 +741,7 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
587
741
);
588
742
}
589
743
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 ]));
591
745
592
746
if (elems [i ] != .none and val != elems [i ]) {
593
747
const elem_node = elem_nodes .at (@intCast (i ));
@@ -650,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
650
804
};
651
805
652
806
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 );
654
808
655
809
if (struct_info .comptime_bits .getBit (ip , name_index )) {
656
810
const val = ip .indexToKey (field_values [name_index ]);
@@ -715,7 +869,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
715
869
const elems = try self .sema .arena .alloc (InternPool .Index , elem_nodes .len + @intFromBool (ptr_info .sentinel != .none ));
716
870
717
871
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 ));
719
873
}
720
874
721
875
if (ptr_info .sentinel != .none ) {
@@ -810,7 +964,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
810
964
if (field_type .toIntern () == .void_type ) {
811
965
return self .fail (field_node , "expected type 'void'" , .{});
812
966
}
813
- break :b try self .lowerExpr (field_node , field_type );
967
+ break :b try self .lowerExprKnownResTy (field_node , field_type );
814
968
} else b : {
815
969
if (field_type .toIntern () != .void_type ) {
816
970
return error .WrongType ;
@@ -846,7 +1000,7 @@ fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
846
1000
}
847
1001
848
1002
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 ));
850
1004
}
851
1005
852
1006
return self .sema .pt .intern (.{ .aggregate = .{
0 commit comments