| author | |
| committer | |
| log | 2a6b91874ae970c0fba63f8c1357da5a57feec27 |
| tree | ccc245020664b0908c3e674295d3e1ca6e01bd10 |
| parent | ab86b2024883f67c0fa06108f66e4e88b98c3163 |
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 implementation16 files changed, 233 insertions(+), 58 deletions(-)
src/InternPool.zig+28-13| ... | ... | @@ -400,14 +400,21 @@ pub const Key = union(enum) { |
| 400 | 400 | /// integer tag type of the enum. |
| 401 | 401 | pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 { |
| 402 | 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 | 410 | if (self.values_map.unwrap()) |values_map| { |
| 404 | 411 | const map = &ip.maps.items[@enumToInt(values_map)]; |
| 405 | 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 | 414 | return @intCast(u32, field_index); |
| 408 | 415 | } |
| 409 | // Auto-numbered enum. Convert `tag_val` to field index. | |
| 410 | switch (ip.indexToKey(tag_val).int.storage) { | |
| 416 | // Auto-numbered enum. Convert `int_tag_val` to field index. | |
| 417 | switch (ip.indexToKey(int_tag_val).int.storage) { | |
| 411 | 418 | .u64 => |x| { |
| 412 | 419 | if (x >= self.names.len) return null; |
| 413 | 420 | return @intCast(u32, x); |
| ... | ... | @@ -4261,12 +4268,8 @@ fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { |
| 4261 | 4268 | |
| 4262 | 4269 | /// This operation only happens under compile error conditions. |
| 4263 | 4270 | /// Leak the index until the next garbage collection. |
| 4264 | pub fn remove(ip: *InternPool, index: Index) void { | |
| 4265 | _ = ip; | |
| 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 | } | |
| 4271 | /// TODO: this is a bit problematic to implement, can we get away without it? | |
| 4272 | pub const remove = @compileError("InternPool.remove is not currently a supported operation; put a TODO there instead"); | |
| 4270 | 4273 | |
| 4271 | 4274 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { |
| 4272 | 4275 | const limbs_len = @intCast(u32, limbs.len); |
| ... | ... | @@ -5161,7 +5164,10 @@ pub fn createStruct( |
| 5161 | 5164 | gpa: Allocator, |
| 5162 | 5165 | initialization: Module.Struct, |
| 5163 | 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 | 5171 | const ptr = try ip.allocated_structs.addOne(gpa); |
| 5166 | 5172 | ptr.* = initialization; |
| 5167 | 5173 | return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1); |
| ... | ... | @@ -5180,7 +5186,10 @@ pub fn createUnion( |
| 5180 | 5186 | gpa: Allocator, |
| 5181 | 5187 | initialization: Module.Union, |
| 5182 | 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 | 5193 | const ptr = try ip.allocated_unions.addOne(gpa); |
| 5185 | 5194 | ptr.* = initialization; |
| 5186 | 5195 | return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1); |
| ... | ... | @@ -5199,7 +5208,10 @@ pub fn createFunc( |
| 5199 | 5208 | gpa: Allocator, |
| 5200 | 5209 | initialization: Module.Fn, |
| 5201 | 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 | 5215 | const ptr = try ip.allocated_funcs.addOne(gpa); |
| 5204 | 5216 | ptr.* = initialization; |
| 5205 | 5217 | return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1); |
| ... | ... | @@ -5218,7 +5230,10 @@ pub fn createInferredErrorSet( |
| 5218 | 5230 | gpa: Allocator, |
| 5219 | 5231 | initialization: Module.Fn.InferredErrorSet, |
| 5220 | 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 | 5237 | const ptr = try ip.allocated_inferred_error_sets.addOne(gpa); |
| 5223 | 5238 | ptr.* = initialization; |
| 5224 | 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 | 4374 | .index = struct_index.toOptional(), |
| 4375 | 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); | |
| 4378 | 4379 | |
| 4379 | 4380 | new_namespace.ty = struct_ty.toType(); |
| 4380 | 4381 | file.root_decl = new_decl_index.toOptional(); |
| ... | ... | @@ -5682,7 +5683,10 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { |
| 5682 | 5683 | } |
| 5683 | 5684 | |
| 5684 | 5685 | pub 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 | 5690 | const ptr = try mod.allocated_namespaces.addOne(mod.gpa); |
| 5687 | 5691 | ptr.* = initialization; |
| 5688 | 5692 | return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1); |
src/Sema.zig+39-18| ... | ... | @@ -2801,7 +2801,8 @@ fn zirStructDecl( |
| 2801 | 2801 | .index = struct_index.toOptional(), |
| 2802 | 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); | |
| 2805 | 2806 | |
| 2806 | 2807 | new_decl.val = struct_ty.toValue(); |
| 2807 | 2808 | new_namespace.ty = struct_ty.toType(); |
| ... | ... | @@ -3012,7 +3013,8 @@ fn zirEnumDecl( |
| 3012 | 3013 | else |
| 3013 | 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); | |
| 3016 | 3018 | |
| 3017 | 3019 | new_decl.val = incomplete_enum.index.toValue(); |
| 3018 | 3020 | new_namespace.ty = incomplete_enum.index.toType(); |
| ... | ... | @@ -3260,7 +3262,8 @@ fn zirUnionDecl( |
| 3260 | 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); | |
| 3264 | 3267 | |
| 3265 | 3268 | new_decl.val = union_ty.toValue(); |
| 3266 | 3269 | new_namespace.ty = union_ty.toType(); |
| ... | ... | @@ -3321,7 +3324,8 @@ fn zirOpaqueDecl( |
| 3321 | 3324 | .decl = new_decl_index, |
| 3322 | 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); | |
| 3325 | 3329 | |
| 3326 | 3330 | new_decl.val = opaque_ty.toValue(); |
| 3327 | 3331 | new_namespace.ty = opaque_ty.toType(); |
| ... | ... | @@ -19424,7 +19428,10 @@ fn zirReify( |
| 19424 | 19428 | }, name_strategy, "enum", inst); |
| 19425 | 19429 | const new_decl = mod.declPtr(new_decl_index); |
| 19426 | 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 | } | |
| 19428 | 19435 | |
| 19429 | 19436 | // Define our empty enum decl |
| 19430 | 19437 | const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod))); |
| ... | ... | @@ -19439,7 +19446,8 @@ fn zirReify( |
| 19439 | 19446 | .explicit, |
| 19440 | 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); | |
| 19443 | 19451 | |
| 19444 | 19452 | new_decl.val = incomplete_enum.index.toValue(); |
| 19445 | 19453 | |
| ... | ... | @@ -19514,7 +19522,10 @@ fn zirReify( |
| 19514 | 19522 | }, name_strategy, "opaque", inst); |
| 19515 | 19523 | const new_decl = mod.declPtr(new_decl_index); |
| 19516 | 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 | } | |
| 19518 | 19529 | |
| 19519 | 19530 | const new_namespace_index = try mod.createNamespace(.{ |
| 19520 | 19531 | .parent = block.namespace.toOptional(), |
| ... | ... | @@ -19528,7 +19539,8 @@ fn zirReify( |
| 19528 | 19539 | .decl = new_decl_index, |
| 19529 | 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); | |
| 19532 | 19544 | |
| 19533 | 19545 | new_decl.val = opaque_ty.toValue(); |
| 19534 | 19546 | new_namespace.ty = opaque_ty.toType(); |
| ... | ... | @@ -19568,7 +19580,10 @@ fn zirReify( |
| 19568 | 19580 | }, name_strategy, "union", inst); |
| 19569 | 19581 | const new_decl = mod.declPtr(new_decl_index); |
| 19570 | 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 | } | |
| 19572 | 19587 | |
| 19573 | 19588 | const new_namespace_index = try mod.createNamespace(.{ |
| 19574 | 19589 | .parent = block.namespace.toOptional(), |
| ... | ... | @@ -19601,7 +19616,8 @@ fn zirReify( |
| 19601 | 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); | |
| 19605 | 19621 | |
| 19606 | 19622 | new_decl.val = union_ty.toValue(); |
| 19607 | 19623 | new_namespace.ty = union_ty.toType(); |
| ... | ... | @@ -19865,7 +19881,10 @@ fn reifyStruct( |
| 19865 | 19881 | }, name_strategy, "struct", inst); |
| 19866 | 19882 | const new_decl = mod.declPtr(new_decl_index); |
| 19867 | 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 | } | |
| 19869 | 19888 | |
| 19870 | 19889 | const new_namespace_index = try mod.createNamespace(.{ |
| 19871 | 19890 | .parent = block.namespace.toOptional(), |
| ... | ... | @@ -19892,7 +19911,8 @@ fn reifyStruct( |
| 19892 | 19911 | .index = struct_index.toOptional(), |
| 19893 | 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); | |
| 19896 | 19916 | |
| 19897 | 19917 | new_decl.val = struct_ty.toValue(); |
| 19898 | 19918 | new_namespace.ty = struct_ty.toType(); |
| ... | ... | @@ -27515,8 +27535,8 @@ fn coerceInMemoryAllowedFns( |
| 27515 | 27535 | if (rt != .ok) { |
| 27516 | 27536 | return InMemoryCoercionResult{ .fn_return_type = .{ |
| 27517 | 27537 | .child = try rt.dupe(sema.arena), |
| 27518 | .actual = dest_return_type, | |
| 27519 | .wanted = src_return_type, | |
| 27538 | .actual = src_return_type, | |
| 27539 | .wanted = dest_return_type, | |
| 27520 | 27540 | } }; |
| 27521 | 27541 | } |
| 27522 | 27542 | }, |
| ... | ... | @@ -29505,7 +29525,8 @@ fn coerceTupleToStruct( |
| 29505 | 29525 | .ty = struct_ty.toIntern(), |
| 29506 | 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); | |
| 29509 | 29530 | |
| 29510 | 29531 | return sema.addConstant(struct_ty, struct_val.toValue()); |
| 29511 | 29532 | } |
| ... | ... | @@ -34666,14 +34687,14 @@ fn floatToIntScalar( |
| 34666 | 34687 | var big_int = try float128IntPartToBigInt(sema.arena, float); |
| 34667 | 34688 | defer big_int.deinit(); |
| 34668 | 34689 | |
| 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()); | |
| 34670 | 34691 | |
| 34671 | if (!(try sema.intFitsInType(result, int_ty, null))) { | |
| 34692 | if (!(try sema.intFitsInType(cti_result, int_ty, null))) { | |
| 34672 | 34693 | return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{ |
| 34673 | 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 | } |
| 34678 | 34699 | |
| 34679 | 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 | 203 | .extern_func => |extern_func| return writer.print("(extern function '{s}')", .{ |
| 204 | 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 | 207 | mod.intern_pool.stringToSlice(mod.declPtr(mod.funcPtr(func.index).owner_decl).name), |
| 208 | 208 | }), |
| 209 | 209 | .int => |int| switch (int.storage) { |
| ... | ... | @@ -234,7 +234,12 @@ pub fn print( |
| 234 | 234 | if (level == 0) { |
| 235 | 235 | return writer.writeAll("(enum)"); |
| 236 | 236 | } |
| 237 | ||
| 237 | 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 | 243 | try writer.writeAll("@intToEnum("); |
| 239 | 244 | try print(.{ |
| 240 | 245 | .ty = Type.type, |
| ... | ... | @@ -250,9 +255,129 @@ pub fn print( |
| 250 | 255 | }, |
| 251 | 256 | .empty_enum_value => return writer.writeAll("(empty enum value)"), |
| 252 | 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 | 381 | .opt => |opt| switch (opt.val) { |
| 257 | 382 | .none => return writer.writeAll("null"), |
| 258 | 383 | else => |payload| { |
| ... | ... | @@ -261,7 +386,15 @@ pub fn print( |
| 261 | 386 | }, |
| 262 | 387 | }, |
| 263 | 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 | 398 | .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod), |
| 266 | 399 | }, |
| 267 | 400 | .un => |un| { |
src/type.zig+3| ... | ... | @@ -345,6 +345,9 @@ pub const Type = struct { |
| 345 | 345 | } |
| 346 | 346 | }, |
| 347 | 347 | .anon_struct_type => |anon_struct| { |
| 348 | if (anon_struct.types.len == 0) { | |
| 349 | return writer.writeAll("@TypeOf(.{})"); | |
| 350 | } | |
| 348 | 351 | try writer.writeAll("struct{"); |
| 349 | 352 | for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| { |
| 350 | 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 | 9 | // target=native |
| 10 | 10 | // |
| 11 | 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 | 14 | // :2:5: error: found compile log statement |
| 15 | 15 | // |
| 16 | 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 | const Set1 = error {A, B}; | |
| 2 | const Set2 = error {A, C}; | |
| 1 | const Set1 = error{ A, B }; | |
| 2 | const Set2 = error{ A, C }; | |
| 3 | 3 | comptime { |
| 4 | 4 | var x = Set1.B; |
| 5 | 5 | var y = @errSetCast(Set2, x); |
| ... | ... | @@ -10,5 +10,4 @@ comptime { |
| 10 | 10 | // backend=stage2 |
| 11 | 11 | // target=native |
| 12 | 12 | // |
| 13 | // :5:13: error: 'error.B' not a member of error set 'error{A,C}' | |
| 14 | // :2:14: note: error set declared here | |
| 13 | // :5:13: error: 'error.B' not a member of error set 'error{C,A}' |
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | const Set1 = error{A, B}; | |
| 2 | const Set2 = error{A, C}; | |
| 1 | const Set1 = error{ A, B }; | |
| 2 | const Set2 = error{ A, C }; | |
| 3 | 3 | export fn entry() void { |
| 4 | 4 | foo(Set1.B); |
| 5 | 5 | } |
| ... | ... | @@ -12,5 +12,5 @@ fn foo(set1: Set1) void { |
| 12 | 12 | // backend=stage2 |
| 13 | 13 | // 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 | 16 | // :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 | 16 | // backend=llvm |
| 17 | 17 | // target=native |
| 18 | 18 | // |
| 19 | // :11:13: error: 'error.B' not a member of error set 'error{A,C}' | |
| 20 | // :5:14: note: error set declared here | |
| 19 | // :11:13: error: 'error.B' not a member of error set 'error{C,A}' |
test/cases/compile_errors/invalid_non-exhaustive_enum_to_union.zig+1-1| ... | ... | @@ -24,5 +24,5 @@ export fn bar() void { |
| 24 | 24 | // |
| 25 | 25 | // :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum |
| 26 | 26 | // :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 | 28 | // :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 | 16 | // backend=stage2 |
| 17 | 17 | // 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 | 20 | // :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 | 22 | // :6:31: note: cast discards const qualifier |
| 23 | 23 | // :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}' |
| 24 | 24 | // :11:19: note: cast discards const qualifier |
test/cases/compile_errors/return_invalid_type_from_test.zig+4-2| ... | ... | @@ -1,8 +1,10 @@ |
| 1 | test "example" { return 1; } | |
| 1 | test "example" { | |
| 2 | return 1; | |
| 3 | } | |
| 2 | 4 | |
| 3 | 5 | // error |
| 4 | 6 | // backend=stage2 |
| 5 | 7 | // target=native |
| 6 | 8 | // 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 | 1 | test "enum" { |
| 2 | const E = enum(u8) {A, B, _}; | |
| 2 | const E = enum(u8) { A, B, _ }; | |
| 3 | 3 | _ = @tagName(@intToEnum(E, 5)); |
| 4 | 4 | } |
| 5 | 5 | |
| ... | ... | @@ -8,5 +8,5 @@ test "enum" { |
| 8 | 8 | // target=native |
| 9 | 9 | // 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 | 12 | // :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 | 41 | // :12:14: error: missing tuple field with index 1 |
| 42 | 42 | // :17:14: error: missing tuple field with index 1 |
| 43 | 43 | // :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 | 7 | // backend=stage2 |
| 8 | 8 | // 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}' |