authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-03 15:46:16+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:51:10-07:00
log2a6b91874ae970c0fba63f8c1357da5a57feec27
treeccc245020664b0908c3e674295d3e1ca6e01bd10
parentab86b2024883f67c0fa06108f66e4e88b98c3163

stage2: pass most test cases under InternPool

All but 2 test cases now pass (tested on x86_64 Linux, native only). The remaining two signify an issue requiring a larger refactor, which I will do in a separate commit. Notable changes: * Fix uninitialized memory when allocating objects from free lists * Implement TypedValue printing for pointers * Fix some TypedValue printing logic * Work around non-existence of InternPool.remove implementation

16 files changed, 233 insertions(+), 58 deletions(-)

src/InternPool.zig+28-13
...@@ -400,14 +400,21 @@ pub const Key = union(enum) {...@@ -400,14 +400,21 @@ pub const Key = union(enum) {
400 /// integer tag type of the enum.400 /// integer tag type of the enum.
401 pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 {401 pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 {
402 assert(tag_val != .none);402 assert(tag_val != .none);
403 // TODO: we should probably decide a single interface for this function, but currently
404 // it's being called with both tag values and underlying ints. Fix this!
405 const int_tag_val = switch (ip.indexToKey(tag_val)) {
406 .enum_tag => |enum_tag| enum_tag.int,
407 .int => tag_val,
408 else => unreachable,
409 };
403 if (self.values_map.unwrap()) |values_map| {410 if (self.values_map.unwrap()) |values_map| {
404 const map = &ip.maps.items[@enumToInt(values_map)];411 const map = &ip.maps.items[@enumToInt(values_map)];
405 const adapter: Index.Adapter = .{ .indexes = self.values };412 const adapter: Index.Adapter = .{ .indexes = self.values };
406 const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null;413 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
407 return @intCast(u32, field_index);414 return @intCast(u32, field_index);
408 }415 }
409 // Auto-numbered enum. Convert `tag_val` to field index.416 // Auto-numbered enum. Convert `int_tag_val` to field index.
410 switch (ip.indexToKey(tag_val).int.storage) {417 switch (ip.indexToKey(int_tag_val).int.storage) {
411 .u64 => |x| {418 .u64 => |x| {
412 if (x >= self.names.len) return null;419 if (x >= self.names.len) return null;
413 return @intCast(u32, x);420 return @intCast(u32, x);
...@@ -4261,12 +4268,8 @@ fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {...@@ -4261,12 +4268,8 @@ fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {
42614268
4262/// This operation only happens under compile error conditions.4269/// This operation only happens under compile error conditions.
4263/// Leak the index until the next garbage collection.4270/// Leak the index until the next garbage collection.
4264pub fn remove(ip: *InternPool, index: Index) void {4271/// TODO: this is a bit problematic to implement, can we get away without it?
4265 _ = ip;4272pub const remove = @compileError("InternPool.remove is not currently a supported operation; put a TODO there instead");
4266 _ = index;
4267 @setCold(true);
4268 @panic("TODO this is a bit problematic to implement, could we maybe just never support a remove() operation on InternPool?");
4269}
42704273
4271fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {4274fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
4272 const limbs_len = @intCast(u32, limbs.len);4275 const limbs_len = @intCast(u32, limbs.len);
...@@ -5161,7 +5164,10 @@ pub fn createStruct(...@@ -5161,7 +5164,10 @@ pub fn createStruct(
5161 gpa: Allocator,5164 gpa: Allocator,
5162 initialization: Module.Struct,5165 initialization: Module.Struct,
5163) Allocator.Error!Module.Struct.Index {5166) Allocator.Error!Module.Struct.Index {
5164 if (ip.structs_free_list.popOrNull()) |index| return index;5167 if (ip.structs_free_list.popOrNull()) |index| {
5168 ip.allocated_structs.at(@enumToInt(index)).* = initialization;
5169 return index;
5170 }
5165 const ptr = try ip.allocated_structs.addOne(gpa);5171 const ptr = try ip.allocated_structs.addOne(gpa);
5166 ptr.* = initialization;5172 ptr.* = initialization;
5167 return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1);5173 return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1);
...@@ -5180,7 +5186,10 @@ pub fn createUnion(...@@ -5180,7 +5186,10 @@ pub fn createUnion(
5180 gpa: Allocator,5186 gpa: Allocator,
5181 initialization: Module.Union,5187 initialization: Module.Union,
5182) Allocator.Error!Module.Union.Index {5188) Allocator.Error!Module.Union.Index {
5183 if (ip.unions_free_list.popOrNull()) |index| return index;5189 if (ip.unions_free_list.popOrNull()) |index| {
5190 ip.allocated_unions.at(@enumToInt(index)).* = initialization;
5191 return index;
5192 }
5184 const ptr = try ip.allocated_unions.addOne(gpa);5193 const ptr = try ip.allocated_unions.addOne(gpa);
5185 ptr.* = initialization;5194 ptr.* = initialization;
5186 return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1);5195 return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1);
...@@ -5199,7 +5208,10 @@ pub fn createFunc(...@@ -5199,7 +5208,10 @@ pub fn createFunc(
5199 gpa: Allocator,5208 gpa: Allocator,
5200 initialization: Module.Fn,5209 initialization: Module.Fn,
5201) Allocator.Error!Module.Fn.Index {5210) Allocator.Error!Module.Fn.Index {
5202 if (ip.funcs_free_list.popOrNull()) |index| return index;5211 if (ip.funcs_free_list.popOrNull()) |index| {
5212 ip.allocated_funcs.at(@enumToInt(index)).* = initialization;
5213 return index;
5214 }
5203 const ptr = try ip.allocated_funcs.addOne(gpa);5215 const ptr = try ip.allocated_funcs.addOne(gpa);
5204 ptr.* = initialization;5216 ptr.* = initialization;
5205 return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1);5217 return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1);
...@@ -5218,7 +5230,10 @@ pub fn createInferredErrorSet(...@@ -5218,7 +5230,10 @@ pub fn createInferredErrorSet(
5218 gpa: Allocator,5230 gpa: Allocator,
5219 initialization: Module.Fn.InferredErrorSet,5231 initialization: Module.Fn.InferredErrorSet,
5220) Allocator.Error!Module.Fn.InferredErrorSet.Index {5232) Allocator.Error!Module.Fn.InferredErrorSet.Index {
5221 if (ip.inferred_error_sets_free_list.popOrNull()) |index| return index;5233 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
5234 ip.allocated_inferred_error_sets.at(@enumToInt(index)).* = initialization;
5235 return index;
5236 }
5222 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);5237 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
5223 ptr.* = initialization;5238 ptr.* = initialization;
5224 return @intToEnum(Module.Fn.InferredErrorSet.Index, ip.allocated_inferred_error_sets.len - 1);5239 return @intToEnum(Module.Fn.InferredErrorSet.Index, ip.allocated_inferred_error_sets.len - 1);
src/Module.zig+6-2
...@@ -4374,7 +4374,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4374,7 +4374,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4374 .index = struct_index.toOptional(),4374 .index = struct_index.toOptional(),
4375 .namespace = new_namespace_index.toOptional(),4375 .namespace = new_namespace_index.toOptional(),
4376 } });4376 } });
4377 errdefer mod.intern_pool.remove(struct_ty);4377 // TODO: figure out InternPool removals for incremental compilation
4378 //errdefer mod.intern_pool.remove(struct_ty);
43784379
4379 new_namespace.ty = struct_ty.toType();4380 new_namespace.ty = struct_ty.toType();
4380 file.root_decl = new_decl_index.toOptional();4381 file.root_decl = new_decl_index.toOptional();
...@@ -5682,7 +5683,10 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5682,7 +5683,10 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5682}5683}
56835684
5684pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {5685pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
5685 if (mod.namespaces_free_list.popOrNull()) |index| return index;5686 if (mod.namespaces_free_list.popOrNull()) |index| {
5687 mod.allocated_namespaces.at(@enumToInt(index)).* = initialization;
5688 return index;
5689 }
5686 const ptr = try mod.allocated_namespaces.addOne(mod.gpa);5690 const ptr = try mod.allocated_namespaces.addOne(mod.gpa);
5687 ptr.* = initialization;5691 ptr.* = initialization;
5688 return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1);5692 return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1);
src/Sema.zig+39-18
...@@ -2801,7 +2801,8 @@ fn zirStructDecl(...@@ -2801,7 +2801,8 @@ fn zirStructDecl(
2801 .index = struct_index.toOptional(),2801 .index = struct_index.toOptional(),
2802 .namespace = new_namespace_index.toOptional(),2802 .namespace = new_namespace_index.toOptional(),
2803 } });2803 } });
2804 errdefer mod.intern_pool.remove(struct_ty);2804 // TODO: figure out InternPool removals for incremental compilation
2805 //errdefer mod.intern_pool.remove(struct_ty);
28052806
2806 new_decl.val = struct_ty.toValue();2807 new_decl.val = struct_ty.toValue();
2807 new_namespace.ty = struct_ty.toType();2808 new_namespace.ty = struct_ty.toType();
...@@ -3012,7 +3013,8 @@ fn zirEnumDecl(...@@ -3012,7 +3013,8 @@ fn zirEnumDecl(
3012 else3013 else
3013 .explicit,3014 .explicit,
3014 });3015 });
3015 errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);3016 // TODO: figure out InternPool removals for incremental compilation
3017 //errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);
30163018
3017 new_decl.val = incomplete_enum.index.toValue();3019 new_decl.val = incomplete_enum.index.toValue();
3018 new_namespace.ty = incomplete_enum.index.toType();3020 new_namespace.ty = incomplete_enum.index.toType();
...@@ -3260,7 +3262,8 @@ fn zirUnionDecl(...@@ -3260,7 +3262,8 @@ fn zirUnionDecl(
3260 .ReleaseFast, .ReleaseSmall => .none,3262 .ReleaseFast, .ReleaseSmall => .none,
3261 },3263 },
3262 } });3264 } });
3263 errdefer mod.intern_pool.remove(union_ty);3265 // TODO: figure out InternPool removals for incremental compilation
3266 //errdefer mod.intern_pool.remove(union_ty);
32643267
3265 new_decl.val = union_ty.toValue();3268 new_decl.val = union_ty.toValue();
3266 new_namespace.ty = union_ty.toType();3269 new_namespace.ty = union_ty.toType();
...@@ -3321,7 +3324,8 @@ fn zirOpaqueDecl(...@@ -3321,7 +3324,8 @@ fn zirOpaqueDecl(
3321 .decl = new_decl_index,3324 .decl = new_decl_index,
3322 .namespace = new_namespace_index,3325 .namespace = new_namespace_index,
3323 } });3326 } });
3324 errdefer mod.intern_pool.remove(opaque_ty);3327 // TODO: figure out InternPool removals for incremental compilation
3328 //errdefer mod.intern_pool.remove(opaque_ty);
33253329
3326 new_decl.val = opaque_ty.toValue();3330 new_decl.val = opaque_ty.toValue();
3327 new_namespace.ty = opaque_ty.toType();3331 new_namespace.ty = opaque_ty.toType();
...@@ -19424,7 +19428,10 @@ fn zirReify(...@@ -19424,7 +19428,10 @@ fn zirReify(
19424 }, name_strategy, "enum", inst);19428 }, name_strategy, "enum", inst);
19425 const new_decl = mod.declPtr(new_decl_index);19429 const new_decl = mod.declPtr(new_decl_index);
19426 new_decl.owns_tv = true;19430 new_decl.owns_tv = true;
19427 errdefer mod.abortAnonDecl(new_decl_index);19431 errdefer {
19432 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19433 mod.abortAnonDecl(new_decl_index);
19434 }
1942819435
19429 // Define our empty enum decl19436 // Define our empty enum decl
19430 const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod)));19437 const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod)));
...@@ -19439,7 +19446,8 @@ fn zirReify(...@@ -19439,7 +19446,8 @@ fn zirReify(
19439 .explicit,19446 .explicit,
19440 .tag_ty = int_tag_ty.toIntern(),19447 .tag_ty = int_tag_ty.toIntern(),
19441 });19448 });
19442 errdefer ip.remove(incomplete_enum.index);19449 // TODO: figure out InternPool removals for incremental compilation
19450 //errdefer ip.remove(incomplete_enum.index);
1944319451
19444 new_decl.val = incomplete_enum.index.toValue();19452 new_decl.val = incomplete_enum.index.toValue();
1944519453
...@@ -19514,7 +19522,10 @@ fn zirReify(...@@ -19514,7 +19522,10 @@ fn zirReify(
19514 }, name_strategy, "opaque", inst);19522 }, name_strategy, "opaque", inst);
19515 const new_decl = mod.declPtr(new_decl_index);19523 const new_decl = mod.declPtr(new_decl_index);
19516 new_decl.owns_tv = true;19524 new_decl.owns_tv = true;
19517 errdefer mod.abortAnonDecl(new_decl_index);19525 errdefer {
19526 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19527 mod.abortAnonDecl(new_decl_index);
19528 }
1951819529
19519 const new_namespace_index = try mod.createNamespace(.{19530 const new_namespace_index = try mod.createNamespace(.{
19520 .parent = block.namespace.toOptional(),19531 .parent = block.namespace.toOptional(),
...@@ -19528,7 +19539,8 @@ fn zirReify(...@@ -19528,7 +19539,8 @@ fn zirReify(
19528 .decl = new_decl_index,19539 .decl = new_decl_index,
19529 .namespace = new_namespace_index,19540 .namespace = new_namespace_index,
19530 } });19541 } });
19531 errdefer ip.remove(opaque_ty);19542 // TODO: figure out InternPool removals for incremental compilation
19543 //errdefer ip.remove(opaque_ty);
1953219544
19533 new_decl.val = opaque_ty.toValue();19545 new_decl.val = opaque_ty.toValue();
19534 new_namespace.ty = opaque_ty.toType();19546 new_namespace.ty = opaque_ty.toType();
...@@ -19568,7 +19580,10 @@ fn zirReify(...@@ -19568,7 +19580,10 @@ fn zirReify(
19568 }, name_strategy, "union", inst);19580 }, name_strategy, "union", inst);
19569 const new_decl = mod.declPtr(new_decl_index);19581 const new_decl = mod.declPtr(new_decl_index);
19570 new_decl.owns_tv = true;19582 new_decl.owns_tv = true;
19571 errdefer mod.abortAnonDecl(new_decl_index);19583 errdefer {
19584 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19585 mod.abortAnonDecl(new_decl_index);
19586 }
1957219587
19573 const new_namespace_index = try mod.createNamespace(.{19588 const new_namespace_index = try mod.createNamespace(.{
19574 .parent = block.namespace.toOptional(),19589 .parent = block.namespace.toOptional(),
...@@ -19601,7 +19616,8 @@ fn zirReify(...@@ -19601,7 +19616,8 @@ fn zirReify(
19601 .ReleaseFast, .ReleaseSmall => .none,19616 .ReleaseFast, .ReleaseSmall => .none,
19602 },19617 },
19603 } });19618 } });
19604 errdefer ip.remove(union_ty);19619 // TODO: figure out InternPool removals for incremental compilation
19620 //errdefer ip.remove(union_ty);
1960519621
19606 new_decl.val = union_ty.toValue();19622 new_decl.val = union_ty.toValue();
19607 new_namespace.ty = union_ty.toType();19623 new_namespace.ty = union_ty.toType();
...@@ -19865,7 +19881,10 @@ fn reifyStruct(...@@ -19865,7 +19881,10 @@ fn reifyStruct(
19865 }, name_strategy, "struct", inst);19881 }, name_strategy, "struct", inst);
19866 const new_decl = mod.declPtr(new_decl_index);19882 const new_decl = mod.declPtr(new_decl_index);
19867 new_decl.owns_tv = true;19883 new_decl.owns_tv = true;
19868 errdefer mod.abortAnonDecl(new_decl_index);19884 errdefer {
19885 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19886 mod.abortAnonDecl(new_decl_index);
19887 }
1986919888
19870 const new_namespace_index = try mod.createNamespace(.{19889 const new_namespace_index = try mod.createNamespace(.{
19871 .parent = block.namespace.toOptional(),19890 .parent = block.namespace.toOptional(),
...@@ -19892,7 +19911,8 @@ fn reifyStruct(...@@ -19892,7 +19911,8 @@ fn reifyStruct(
19892 .index = struct_index.toOptional(),19911 .index = struct_index.toOptional(),
19893 .namespace = new_namespace_index.toOptional(),19912 .namespace = new_namespace_index.toOptional(),
19894 } });19913 } });
19895 errdefer ip.remove(struct_ty);19914 // TODO: figure out InternPool removals for incremental compilation
19915 //errdefer ip.remove(struct_ty);
1989619916
19897 new_decl.val = struct_ty.toValue();19917 new_decl.val = struct_ty.toValue();
19898 new_namespace.ty = struct_ty.toType();19918 new_namespace.ty = struct_ty.toType();
...@@ -27515,8 +27535,8 @@ fn coerceInMemoryAllowedFns(...@@ -27515,8 +27535,8 @@ fn coerceInMemoryAllowedFns(
27515 if (rt != .ok) {27535 if (rt != .ok) {
27516 return InMemoryCoercionResult{ .fn_return_type = .{27536 return InMemoryCoercionResult{ .fn_return_type = .{
27517 .child = try rt.dupe(sema.arena),27537 .child = try rt.dupe(sema.arena),
27518 .actual = dest_return_type,27538 .actual = src_return_type,
27519 .wanted = src_return_type,27539 .wanted = dest_return_type,
27520 } };27540 } };
27521 }27541 }
27522 },27542 },
...@@ -29505,7 +29525,8 @@ fn coerceTupleToStruct(...@@ -29505,7 +29525,8 @@ fn coerceTupleToStruct(
29505 .ty = struct_ty.toIntern(),29525 .ty = struct_ty.toIntern(),
29506 .storage = .{ .elems = field_vals },29526 .storage = .{ .elems = field_vals },
29507 } });29527 } });
29508 errdefer ip.remove(struct_val);29528 // TODO: figure out InternPool removals for incremental compilation
29529 //errdefer ip.remove(struct_val);
2950929530
29510 return sema.addConstant(struct_ty, struct_val.toValue());29531 return sema.addConstant(struct_ty, struct_val.toValue());
29511}29532}
...@@ -34666,14 +34687,14 @@ fn floatToIntScalar(...@@ -34666,14 +34687,14 @@ fn floatToIntScalar(
34666 var big_int = try float128IntPartToBigInt(sema.arena, float);34687 var big_int = try float128IntPartToBigInt(sema.arena, float);
34667 defer big_int.deinit();34688 defer big_int.deinit();
3466834689
34669 const result = try mod.intValue_big(int_ty, big_int.toConst());34690 const cti_result = try mod.intValue_big(Type.comptime_int, big_int.toConst());
3467034691
34671 if (!(try sema.intFitsInType(result, int_ty, null))) {34692 if (!(try sema.intFitsInType(cti_result, int_ty, null))) {
34672 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{34693 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
34673 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),34694 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),
34674 });34695 });
34675 }34696 }
34676 return result;34697 return mod.getCoerced(cti_result, int_ty);
34677}34698}
3467834699
34679/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.34700/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
src/TypedValue.zig+138-5
...@@ -203,7 +203,7 @@ pub fn print(...@@ -203,7 +203,7 @@ pub fn print(
203 .extern_func => |extern_func| return writer.print("(extern function '{s}')", .{203 .extern_func => |extern_func| return writer.print("(extern function '{s}')", .{
204 mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name),204 mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name),
205 }),205 }),
206 .func => |func| return writer.print("(function '{d}')", .{206 .func => |func| return writer.print("(function '{s}')", .{
207 mod.intern_pool.stringToSlice(mod.declPtr(mod.funcPtr(func.index).owner_decl).name),207 mod.intern_pool.stringToSlice(mod.declPtr(mod.funcPtr(func.index).owner_decl).name),
208 }),208 }),
209 .int => |int| switch (int.storage) {209 .int => |int| switch (int.storage) {
...@@ -234,7 +234,12 @@ pub fn print(...@@ -234,7 +234,12 @@ pub fn print(
234 if (level == 0) {234 if (level == 0) {
235 return writer.writeAll("(enum)");235 return writer.writeAll("(enum)");
236 }236 }
237237 const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type;
238 if (enum_type.tagValueIndex(&mod.intern_pool, val.toIntern())) |tag_index| {
239 const tag_name = mod.intern_pool.stringToSlice(enum_type.names[tag_index]);
240 try writer.print(".{}", .{std.zig.fmtId(tag_name)});
241 return;
242 }
238 try writer.writeAll("@intToEnum(");243 try writer.writeAll("@intToEnum(");
239 try print(.{244 try print(.{
240 .ty = Type.type,245 .ty = Type.type,
...@@ -250,9 +255,129 @@ pub fn print(...@@ -250,9 +255,129 @@ pub fn print(
250 },255 },
251 .empty_enum_value => return writer.writeAll("(empty enum value)"),256 .empty_enum_value => return writer.writeAll("(empty enum value)"),
252 .float => |float| switch (float.storage) {257 .float => |float| switch (float.storage) {
253 inline else => |x| return writer.print("{}", .{x}),258 inline else => |x| return writer.print("{d}", .{@floatCast(f64, x)}),
259 },
260 .ptr => |ptr| {
261 if (ptr.addr == .int) {
262 const i = mod.intern_pool.indexToKey(ptr.addr.int).int;
263 switch (i.storage) {
264 inline else => |addr| return writer.print("{x:0>8}", .{addr}),
265 }
266 }
267
268 const ptr_ty = mod.intern_pool.indexToKey(ty.toIntern()).ptr_type;
269 if (ptr_ty.flags.size == .Slice) {
270 if (level == 0) {
271 return writer.writeAll(".{ ... }");
272 }
273 const elem_ty = ptr_ty.child.toType();
274 const len = ptr.len.toValue().toUnsignedInt(mod);
275 if (elem_ty.eql(Type.u8, mod)) str: {
276 const max_len = @min(len, max_string_len);
277 var buf: [max_string_len]u8 = undefined;
278 for (buf[0..max_len], 0..) |*c, i| {
279 const elem = try val.elemValue(mod, i);
280 if (elem.isUndef(mod)) break :str;
281 c.* = @intCast(u8, elem.toUnsignedInt(mod));
282 }
283 const truncated = if (len > max_string_len) " (truncated)" else "";
284 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
285 }
286 try writer.writeAll(".{ ");
287 const max_len = @min(len, max_aggregate_items);
288 for (0..max_len) |i| {
289 if (i != 0) try writer.writeAll(", ");
290 try print(.{
291 .ty = elem_ty,
292 .val = try val.elemValue(mod, i),
293 }, writer, level - 1, mod);
294 }
295 if (len > max_aggregate_items) {
296 try writer.writeAll(", ...");
297 }
298 return writer.writeAll(" }");
299 }
300
301 switch (ptr.addr) {
302 .decl => |decl_index| {
303 const decl = mod.declPtr(decl_index);
304 if (level == 0) return writer.print("(decl '{s}')", .{mod.intern_pool.stringToSlice(decl.name)});
305 return print(.{
306 .ty = decl.ty,
307 .val = decl.val,
308 }, writer, level - 1, mod);
309 },
310 .mut_decl => |mut_decl| {
311 const decl = mod.declPtr(mut_decl.decl);
312 if (level == 0) return writer.print("(mut decl '{s}')", .{mod.intern_pool.stringToSlice(decl.name)});
313 return print(.{
314 .ty = decl.ty,
315 .val = decl.val,
316 }, writer, level - 1, mod);
317 },
318 .comptime_field => |field_val_ip| {
319 return print(.{
320 .ty = mod.intern_pool.typeOf(field_val_ip).toType(),
321 .val = field_val_ip.toValue(),
322 }, writer, level - 1, mod);
323 },
324 .int => unreachable,
325 .eu_payload => |eu_ip| {
326 try writer.writeAll("(payload of ");
327 try print(.{
328 .ty = mod.intern_pool.typeOf(eu_ip).toType(),
329 .val = eu_ip.toValue(),
330 }, writer, level - 1, mod);
331 try writer.writeAll(")");
332 },
333 .opt_payload => |opt_ip| {
334 try print(.{
335 .ty = mod.intern_pool.typeOf(opt_ip).toType(),
336 .val = opt_ip.toValue(),
337 }, writer, level - 1, mod);
338 try writer.writeAll(".?");
339 },
340 .elem => |elem| {
341 try print(.{
342 .ty = mod.intern_pool.typeOf(elem.base).toType(),
343 .val = elem.base.toValue(),
344 }, writer, level - 1, mod);
345 try writer.print("[{}]", .{elem.index});
346 },
347 .field => |field| {
348 const container_ty = mod.intern_pool.typeOf(field.base).toType();
349 try print(.{
350 .ty = container_ty,
351 .val = field.base.toValue(),
352 }, writer, level - 1, mod);
353
354 switch (container_ty.zigTypeTag(mod)) {
355 .Struct => {
356 if (container_ty.isTuple(mod)) {
357 try writer.print("[{d}]", .{field.index});
358 }
359 const field_name_ip = container_ty.structFieldName(field.index, mod);
360 const field_name = mod.intern_pool.stringToSlice(field_name_ip);
361 try writer.print(".{}", .{std.zig.fmtId(field_name)});
362 },
363 .Union => {
364 const field_name_ip = container_ty.unionFields(mod).keys()[field.index];
365 const field_name = mod.intern_pool.stringToSlice(field_name_ip);
366 try writer.print(".{}", .{std.zig.fmtId(field_name)});
367 },
368 .Pointer => {
369 std.debug.assert(container_ty.isSlice(mod));
370 try writer.writeAll(switch (field.index) {
371 Value.slice_ptr_index => ".ptr",
372 Value.slice_len_index => ".len",
373 else => unreachable,
374 });
375 },
376 else => unreachable,
377 }
378 },
379 }
254 },380 },
255 .ptr => return writer.writeAll("(ptr)"),
256 .opt => |opt| switch (opt.val) {381 .opt => |opt| switch (opt.val) {
257 .none => return writer.writeAll("null"),382 .none => return writer.writeAll("null"),
258 else => |payload| {383 else => |payload| {
...@@ -261,7 +386,15 @@ pub fn print(...@@ -261,7 +386,15 @@ pub fn print(
261 },386 },
262 },387 },
263 .aggregate => |aggregate| switch (aggregate.storage) {388 .aggregate => |aggregate| switch (aggregate.storage) {
264 .bytes => |bytes| return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),389 .bytes => |bytes| {
390 // Strip the 0 sentinel off of strings before printing
391 const zero_sent = blk: {
392 const sent = ty.sentinel(mod) orelse break :blk false;
393 break :blk sent.eql(Value.zero_u8, Type.u8, mod);
394 };
395 const str = if (zero_sent) bytes[0..bytes.len - 1] else bytes;
396 return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)});
397 },
265 .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),398 .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),
266 },399 },
267 .un => |un| {400 .un => |un| {
src/type.zig+3
...@@ -345,6 +345,9 @@ pub const Type = struct {...@@ -345,6 +345,9 @@ pub const Type = struct {
345 }345 }
346 },346 },
347 .anon_struct_type => |anon_struct| {347 .anon_struct_type => |anon_struct| {
348 if (anon_struct.types.len == 0) {
349 return writer.writeAll("@TypeOf(.{})");
350 }
348 try writer.writeAll("struct{");351 try writer.writeAll("struct{");
349 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {352 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
350 if (i != 0) try writer.writeAll(", ");353 if (i != 0) try writer.writeAll(", ");
test/cases/compile_errors/access_non-existent_member_of_error_set.zig-1
...@@ -9,4 +9,3 @@ comptime {...@@ -9,4 +9,3 @@ comptime {
9// target=native9// target=native
10//10//
11// :3:18: error: no error named 'Bar' in 'error{A}'11// :3:18: error: no error named 'Bar' in 'error{A}'
12// :1:13: note: error set declared here
test/cases/compile_errors/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig+1-1
...@@ -14,4 +14,4 @@ export fn entry() void {...@@ -14,4 +14,4 @@ export fn entry() void {
14// :2:5: error: found compile log statement14// :2:5: error: found compile log statement
15//15//
16// Compile Log Output:16// Compile Log Output:
17// @as(*const [3:0]u8, "i32\x00")17// @as(*const [3:0]u8, "i32")
test/cases/compile_errors/explicit_error_set_cast_known_at_comptime_violates_error_sets.zig+3-4
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const Set1 = error {A, B};1const Set1 = error{ A, B };
2const Set2 = error {A, C};2const Set2 = error{ A, C };
3comptime {3comptime {
4 var x = Set1.B;4 var x = Set1.B;
5 var y = @errSetCast(Set2, x);5 var y = @errSetCast(Set2, x);
...@@ -10,5 +10,4 @@ comptime {...@@ -10,5 +10,4 @@ comptime {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :5:13: error: 'error.B' not a member of error set 'error{A,C}'13// :5:13: error: 'error.B' not a member of error set 'error{C,A}'
14// :2:14: note: error set declared here
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const Set1 = error{A, B};1const Set1 = error{ A, B };
2const Set2 = error{A, C};2const Set2 = error{ A, C };
3export fn entry() void {3export fn entry() void {
4 foo(Set1.B);4 foo(Set1.B);
5}5}
...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :7:19: error: expected type 'error{A,C}', found 'error{A,B}'15// :7:19: error: expected type 'error{C,A}', found 'error{A,B}'
16// :7:19: note: 'error.B' not a member of destination error set16// :7:19: note: 'error.B' not a member of destination error set
test/cases/compile_errors/int_to_err_non_global_invalid_number.zig+1-2
...@@ -16,5 +16,4 @@ comptime {...@@ -16,5 +16,4 @@ comptime {
16// backend=llvm16// backend=llvm
17// target=native17// target=native
18//18//
19// :11:13: error: 'error.B' not a member of error set 'error{A,C}'19// :11:13: error: 'error.B' not a member of error set 'error{C,A}'
20// :5:14: note: error set declared here
test/cases/compile_errors/invalid_non-exhaustive_enum_to_union.zig+1-1
...@@ -24,5 +24,5 @@ export fn bar() void {...@@ -24,5 +24,5 @@ export fn bar() void {
24//24//
25// :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum25// :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum
26// :1:11: note: enum declared here26// :1:11: note: enum declared here
27// :17:16: error: union 'tmp.U' has no tag with value '15'27// :17:16: error: union 'tmp.U' has no tag with value '@intToEnum(tmp.E, 15)'
28// :6:11: note: union declared here28// :6:11: note: union declared here
test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig+2-2
...@@ -16,9 +16,9 @@ comptime {...@@ -16,9 +16,9 @@ comptime {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :2:29: error: expected type '[][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'19// :2:29: error: expected type '[][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
20// :2:29: note: cast discards const qualifier20// :2:29: note: cast discards const qualifier
21// :6:31: error: expected type '*[2][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'21// :6:31: error: expected type '*[2][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
22// :6:31: note: cast discards const qualifier22// :6:31: note: cast discards const qualifier
23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'
24// :11:19: note: cast discards const qualifier24// :11:19: note: cast discards const qualifier
test/cases/compile_errors/return_invalid_type_from_test.zig+4-2
...@@ -1,8 +1,10 @@...@@ -1,8 +1,10 @@
1test "example" { return 1; }1test "example" {
2 return 1;
3}
24
3// error5// error
4// backend=stage26// backend=stage2
5// target=native7// target=native
6// is_test=18// is_test=1
7//9//
8// :1:25: error: expected type '@typeInfo(@typeInfo(@TypeOf(tmp.test.example)).Fn.return_type.?).ErrorUnion.error_set!void', found 'comptime_int'
\ No newline at end of file
10// :2:12: error: expected type 'anyerror!void', found 'comptime_int'
test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1test "enum" {1test "enum" {
2 const E = enum(u8) {A, B, _};2 const E = enum(u8) { A, B, _ };
3 _ = @tagName(@intToEnum(E, 5));3 _ = @tagName(@intToEnum(E, 5));
4}4}
55
...@@ -8,5 +8,5 @@ test "enum" {...@@ -8,5 +8,5 @@ test "enum" {
8// target=native8// target=native
9// is_test=19// is_test=1
10//10//
11// :3:9: error: no field with value '5' in enum 'test.enum.E'11// :3:9: error: no field with value '@intToEnum(tmp.test.enum.E, 5)' in enum 'test.enum.E'
12// :2:15: note: declared here12// :2:15: note: declared here
test/cases/compile_errors/tuple_init_edge_cases.zig+1-1
...@@ -41,4 +41,4 @@ pub export fn entry5() void {...@@ -41,4 +41,4 @@ pub export fn entry5() void {
41// :12:14: error: missing tuple field with index 141// :12:14: error: missing tuple field with index 1
42// :17:14: error: missing tuple field with index 142// :17:14: error: missing tuple field with index 1
43// :29:14: error: expected at most 2 tuple fields; found 343// :29:14: error: expected at most 2 tuple fields; found 3
44// :34:30: error: index '2' out of bounds of tuple 'tuple{comptime comptime_int = 123, u32}'44// :34:30: error: index '2' out of bounds of tuple 'struct{comptime comptime_int = 123, u32}'
test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig+1-1
...@@ -7,4 +7,4 @@ export fn entry() void {...@@ -7,4 +7,4 @@ export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:11: error: expected type '@TypeOf(.{})', found 'tuple{comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3}'10// :3:11: error: expected type '@TypeOf(.{})', found 'struct{comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3}'