| 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,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 { |
| 4261 | 4268 | ||
| 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. |
| 4264 | pub fn remove(ip: *InternPool, index: Index) void { | 4271 | /// TODO: this is a bit problematic to implement, can we get away without it? |
| 4265 | _ = ip; | 4272 | pub 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 | } | ||
| 4270 | 4273 | ||
| 4271 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { | 4274 | fn 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); | ||
| 4378 | 4379 | ||
| 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 | } |
| 5683 | 5684 | ||
| 5684 | pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { | 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 | 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); | ||
| 2805 | 2806 | ||
| 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 | else | 3013 | 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); | ||
| 3016 | 3018 | ||
| 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); | ||
| 3264 | 3267 | ||
| 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); | ||
| 3325 | 3329 | ||
| 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 | } | ||
| 19428 | 19435 | ||
| 19429 | // Define our empty enum decl | 19436 | // 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); | ||
| 19443 | 19451 | ||
| 19444 | new_decl.val = incomplete_enum.index.toValue(); | 19452 | new_decl.val = incomplete_enum.index.toValue(); |
| 19445 | 19453 | ||
| ... | @@ -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 | } | ||
| 19518 | 19529 | ||
| 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); | ||
| 19532 | 19544 | ||
| 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 | } | ||
| 19572 | 19587 | ||
| 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); | ||
| 19605 | 19621 | ||
| 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 | } | ||
| 19869 | 19888 | ||
| 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); | ||
| 19896 | 19916 | ||
| 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); | ||
| 29509 | 29530 | ||
| 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(); |
| 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 | 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 | } |
| 34678 | 34699 | ||
| 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 | } |
| 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 | 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=native | 9 | // 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 statement | 14 | // :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 @@ |
| 1 | const Set1 = error {A, B}; | 1 | const Set1 = error{ A, B }; |
| 2 | const Set2 = error {A, C}; | 2 | const Set2 = error{ A, C }; |
| 3 | comptime { | 3 | comptime { |
| 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=stage2 | 10 | // backend=stage2 |
| 11 | // target=native | 11 | // 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 @@ |
| 1 | const Set1 = error{A, B}; | 1 | const Set1 = error{ A, B }; |
| 2 | const Set2 = error{A, C}; | 2 | const Set2 = error{ A, C }; |
| 3 | export fn entry() void { | 3 | export 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=stage2 | 12 | // backend=stage2 |
| 13 | // target=native | 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 | // :7:19: note: 'error.B' not a member of destination error set | 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,5 +16,4 @@ comptime { |
| 16 | // backend=llvm | 16 | // backend=llvm |
| 17 | // target=native | 17 | // 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 enum | 25 | // :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum |
| 26 | // :1:11: note: enum declared here | 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 | // :6:11: note: union declared here | 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,9 +16,9 @@ comptime { |
| 16 | // backend=stage2 | 16 | // backend=stage2 |
| 17 | // target=native | 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 | // :2:29: note: cast discards const qualifier | 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 | // :6:31: note: cast discards const qualifier | 22 | // :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 qualifier | 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,8 +1,10 @@ |
| 1 | test "example" { return 1; } | 1 | test "example" { |
| 2 | return 1; | ||
| 3 | } | ||
| 2 | 4 | ||
| 3 | // error | 5 | // error |
| 4 | // backend=stage2 | 6 | // backend=stage2 |
| 5 | // target=native | 7 | // target=native |
| 6 | // is_test=1 | 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,5 +1,5 @@ |
| 1 | test "enum" { | 1 | test "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 | } |
| 5 | 5 | ||
| ... | @@ -8,5 +8,5 @@ test "enum" { | ... | @@ -8,5 +8,5 @@ test "enum" { |
| 8 | // target=native | 8 | // target=native |
| 9 | // is_test=1 | 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 | // :2:15: note: declared here | 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,4 +41,4 @@ pub export fn entry5() void { |
| 41 | // :12:14: error: missing tuple field with index 1 | 41 | // :12:14: error: missing tuple field with index 1 |
| 42 | // :17:14: error: missing tuple field with index 1 | 42 | // :17:14: error: missing tuple field with index 1 |
| 43 | // :29:14: error: expected at most 2 tuple fields; found 3 | 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,4 +7,4 @@ export fn entry() void { |
| 7 | // backend=stage2 | 7 | // backend=stage2 |
| 8 | // target=native | 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}' |