authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 11:07:31-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 11:07:31-07:00
log2d8d681b5ee34663aa87f0583f7b1a012b17d5b4
treefefb28fbbdc9ab0c94c41a8609402077307ce024
parent5d696b0706de2ac267cb774ef39e0d81131d5c38

stage2: un-tangle memory management of Decl and Namespace

Before there was this "top_decl" and "tmp_namespace" stack values that were kludgy and buggy. Now Sema is slightly reworked so that files which are structs are analyzed with their own Decl and Namespace already set up. After this commit there are no memory leaks for a successful build-obj.

3 files changed, 138 insertions(+), 101 deletions(-)

src/Module.zig+83-72
...@@ -276,11 +276,16 @@ pub const Decl = struct {...@@ -276,11 +276,16 @@ pub const Decl = struct {
276276
277 pub fn destroy(decl: *Decl, module: *Module) void {277 pub fn destroy(decl: *Decl, module: *Module) void {
278 const gpa = module.gpa;278 const gpa = module.gpa;
279 log.debug("destroy Decl {s}", .{decl.name});
279 decl.clearName(gpa);280 decl.clearName(gpa);
280 if (decl.has_tv) {281 if (decl.has_tv) {
281 if (decl.val.castTag(.function)) |payload| {282 if (decl.val.castTag(.function)) |payload| {
282 const func = payload.data;283 const func = payload.data;
283 func.deinit(gpa);284 func.deinit(gpa);
285 } else if (decl.val.getTypeNamespace()) |namespace| {
286 if (namespace.getDecl() == decl) {
287 namespace.clearDecls(module);
288 }
284 }289 }
285 decl.clearValues(gpa);290 decl.clearValues(gpa);
286 }291 }
...@@ -303,6 +308,13 @@ pub const Decl = struct {...@@ -303,6 +308,13 @@ pub const Decl = struct {
303 }308 }
304 }309 }
305310
311 pub fn finalizeNewArena(decl: *Decl, arena: *std.heap.ArenaAllocator) !void {
312 assert(decl.value_arena == null);
313 const arena_state = try arena.allocator.create(std.heap.ArenaAllocator.State);
314 arena_state.* = arena.state;
315 decl.value_arena = arena_state;
316 }
317
306 /// This name is relative to the containing namespace of the decl.318 /// This name is relative to the containing namespace of the decl.
307 /// The memory is owned by the containing File ZIR.319 /// The memory is owned by the containing File ZIR.
308 pub fn getName(decl: Decl) ?[:0]const u8 {320 pub fn getName(decl: Decl) ?[:0]const u8 {
...@@ -719,13 +731,20 @@ pub const Scope = struct {...@@ -719,13 +731,20 @@ pub const Scope = struct {
719 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},731 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},
720732
721 pub fn deinit(ns: *Namespace, mod: *Module) void {733 pub fn deinit(ns: *Namespace, mod: *Module) void {
734 ns.clearDecls(mod);
735 ns.* = undefined;
736 }
737
738 pub fn clearDecls(ns: *Namespace, mod: *Module) void {
722 const gpa = mod.gpa;739 const gpa = mod.gpa;
723740
724 for (ns.decls.items()) |entry| {741 var decls = ns.decls;
742 ns.decls = .{};
743
744 for (decls.items()) |entry| {
725 entry.value.destroy(mod);745 entry.value.destroy(mod);
726 }746 }
727 ns.decls.deinit(gpa);747 decls.deinit(gpa);
728 ns.* = undefined;
729 }748 }
730749
731 pub fn removeDecl(ns: *Namespace, child: *Decl) void {750 pub fn removeDecl(ns: *Namespace, child: *Decl) void {
...@@ -775,14 +794,9 @@ pub const Scope = struct {...@@ -775,14 +794,9 @@ pub const Scope = struct {
775 /// Package that this file is a part of, managed externally.794 /// Package that this file is a part of, managed externally.
776 pkg: *Package,795 pkg: *Package,
777 /// The namespace of the struct that represents this file.796 /// The namespace of the struct that represents this file.
778 /// Populated only when status is success.797 /// Populated only when status is `success_air`.
779 /// Owned by its owner Decl Value.798 /// Owned by its owner Decl Value.
780 namespace: *Namespace,799 namespace: *Namespace,
781 /// All namespaces that this file contains. This is here so that
782 /// when a file is updated, and new ZIR code is generated, the
783 /// old and new ZIR code can be compared side by side and references
784 /// to old ZIR updated to new ZIR, and a changelist generated.
785 namespace_set: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{},
786800
787 pub fn unload(file: *File, gpa: *Allocator) void {801 pub fn unload(file: *File, gpa: *Allocator) void {
788 file.unloadTree(gpa);802 file.unloadTree(gpa);
...@@ -813,6 +827,10 @@ pub const Scope = struct {...@@ -813,6 +827,10 @@ pub const Scope = struct {
813827
814 pub fn deinit(file: *File, mod: *Module) void {828 pub fn deinit(file: *File, mod: *Module) void {
815 const gpa = mod.gpa;829 const gpa = mod.gpa;
830 log.debug("deinit File {s}", .{file.sub_file_path});
831 if (file.status == .success_air) {
832 file.namespace.getDecl().destroy(mod);
833 }
816 gpa.free(file.sub_file_path);834 gpa.free(file.sub_file_path);
817 file.unload(gpa);835 file.unload(gpa);
818 file.* = undefined;836 file.* = undefined;
...@@ -866,6 +884,18 @@ pub const Scope = struct {...@@ -866,6 +884,18 @@ pub const Scope = struct {
866 gpa.destroy(file);884 gpa.destroy(file);
867 }885 }
868886
887 pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 {
888 // Convert all the slashes into dots and truncate the extension.
889 const ext = std.fs.path.extension(file.sub_file_path);
890 const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len];
891 const duped = try gpa.dupeZ(u8, noext);
892 for (duped) |*byte| switch (byte.*) {
893 '/', '\\' => byte.* = '.',
894 else => continue,
895 };
896 return duped;
897 }
898
869 pub fn dumpSrc(file: *File, src: LazySrcLoc) void {899 pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
870 const loc = std.zig.findLineColumn(file.source.bytes, src);900 const loc = std.zig.findLineColumn(file.source.bytes, src);
871 std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });901 std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });
...@@ -3297,48 +3327,49 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3297,48 +3327,49 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3297 assert(file.zir_loaded);3327 assert(file.zir_loaded);
32983328
3299 const gpa = mod.gpa;3329 const gpa = mod.gpa;
3300 var decl_arena = std.heap.ArenaAllocator.init(gpa);3330 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
3301 defer decl_arena.deinit();3331 errdefer new_decl_arena.deinit();
33023332
3303 // We need a Decl to pass to Sema and collect dependencies. But ultimately we3333 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
3304 // want to pass them on to the Decl for the struct that represents the file.3334 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
3305 var tmp_namespace: Scope.Namespace = .{3335 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
3306 .parent = null,3336 struct_obj.* = .{
3307 .file_scope = file,3337 .owner_decl = undefined, // set below
3308 .ty = Type.initTag(.type),3338 .fields = .{},
3339 .node_offset = 0, // it's the struct for the root file
3340 .namespace = .{
3341 .parent = null,
3342 .ty = struct_ty,
3343 .file_scope = file,
3344 },
3309 };3345 };
3310 var top_decl: Decl = .{3346 file.namespace = &struct_obj.namespace;
3311 .name = "",3347 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);
3312 .namespace = &tmp_namespace,3348 struct_obj.owner_decl = new_decl;
3313 .generation = mod.generation,3349 new_decl.name = try file.fullyQualifiedNameZ(gpa);
3314 .src_node = 0, // the root AST node for the file3350 new_decl.is_pub = true;
3315 .analysis = .in_progress,3351 new_decl.is_exported = false;
3316 .deletion_flag = false,3352 new_decl.has_align = false;
3317 .is_pub = true,3353 new_decl.has_linksection = false;
3318 .is_exported = false,3354 new_decl.zir_decl_index = undefined;
3319 .has_linksection = false,3355 new_decl.ty = struct_ty;
3320 .has_align = false,3356 new_decl.val = struct_val;
3321 .link = undefined, // don't try to codegen this3357 new_decl.has_tv = true;
3322 .fn_link = undefined, // not a function3358 new_decl.analysis = .complete;
3323 .zir_decl_index = undefined,3359 new_decl.generation = mod.generation;
33243360
3325 .has_tv = false,3361 var sema_arena = std.heap.ArenaAllocator.init(gpa);
3326 .ty = undefined,3362 defer sema_arena.deinit();
3327 .val = undefined,
3328 .align_val = undefined,
3329 .linksection_val = undefined,
3330 };
3331 defer top_decl.dependencies.deinit(gpa);
33323363
3333 var sema: Sema = .{3364 var sema: Sema = .{
3334 .mod = mod,3365 .mod = mod,
3335 .gpa = gpa,3366 .gpa = gpa,
3336 .arena = &decl_arena.allocator,3367 .arena = &sema_arena.allocator,
3337 .code = file.zir,3368 .code = file.zir,
3338 // TODO use a map because this array is too big3369 // TODO use a map because this array is too big
3339 .inst_map = try decl_arena.allocator.alloc(*ir.Inst, file.zir.instructions.len),3370 .inst_map = try sema_arena.allocator.alloc(*ir.Inst, file.zir.instructions.len),
3340 .owner_decl = &top_decl,3371 .owner_decl = new_decl,
3341 .namespace = &tmp_namespace,3372 .namespace = &struct_obj.namespace,
3342 .func = null,3373 .func = null,
3343 .owner_func = null,3374 .owner_func = null,
3344 .param_inst_list = &.{},3375 .param_inst_list = &.{},
...@@ -3346,7 +3377,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3346,7 +3377,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3346 var block_scope: Scope.Block = .{3377 var block_scope: Scope.Block = .{
3347 .parent = null,3378 .parent = null,
3348 .sema = &sema,3379 .sema = &sema,
3349 .src_decl = &top_decl,3380 .src_decl = new_decl,
3350 .instructions = .{},3381 .instructions = .{},
3351 .inlining = null,3382 .inlining = null,
3352 .is_comptime = true,3383 .is_comptime = true,
...@@ -3355,23 +3386,9 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3355,23 +3386,9 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
33553386
3356 const main_struct_inst = file.zir.extra[@enumToInt(Zir.ExtraIndex.main_struct)] -3387 const main_struct_inst = file.zir.extra[@enumToInt(Zir.ExtraIndex.main_struct)] -
3357 @intCast(u32, Zir.Inst.Ref.typed_value_map.len);3388 @intCast(u32, Zir.Inst.Ref.typed_value_map.len);
3358 const air_inst = try sema.zirStructDecl(&block_scope, main_struct_inst, .Auto);3389 try sema.analyzeStructDecl(&block_scope, &new_decl_arena, new_decl, main_struct_inst, .Auto, struct_obj);
3359 assert(air_inst.ty.zigTypeTag() == .Type);3390 try new_decl.finalizeNewArena(&new_decl_arena);
3360 const val = air_inst.value().?;3391
3361 const struct_ty = try val.toType(&decl_arena.allocator);
3362 const struct_decl = struct_ty.getOwnerDecl();
3363
3364 file.namespace = struct_ty.getNamespace().?;
3365 file.namespace.parent = null;
3366
3367 // Transfer the dependencies to `owner_decl`.
3368 assert(top_decl.dependants.count() == 0);
3369 for (top_decl.dependencies.items()) |entry| {
3370 const dep = entry.key;
3371 dep.removeDependant(&top_decl);
3372 if (dep == struct_decl) continue;
3373 _ = try mod.declareDeclDependency(struct_decl, dep);
3374 }
3375 file.status = .success_air;3392 file.status = .success_air;
3376}3393}
33773394
...@@ -4319,23 +4336,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b...@@ -4319,23 +4336,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
4319 }4336 }
4320}4337}
43214338
4322pub fn createAnonymousDecl(4339pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
4323 mod: *Module,
4324 scope: *Scope,
4325 decl_arena: *std.heap.ArenaAllocator,
4326 typed_value: TypedValue,
4327) !*Decl {
4328 const name_index = mod.getNextAnonNameIndex();4340 const name_index = mod.getNextAnonNameIndex();
4329 const scope_decl = scope.ownerDecl().?;4341 const scope_decl = scope.ownerDecl().?;
4342 const namespace = scope_decl.namespace;
4343 try namespace.decls.ensureCapacity(mod.gpa, namespace.decls.count() + 1);
4330 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });4344 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
4331 errdefer mod.gpa.free(name);4345 errdefer mod.gpa.free(name);
4332 const namespace = scope_decl.namespace;
4333 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);4346 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
4334 new_decl.name = name;4347 namespace.decls.putAssumeCapacityNoClobber(name, new_decl);
43354348
4336 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);4349 new_decl.name = name;
4337
4338 decl_arena_state.* = decl_arena.state;
4339 new_decl.ty = typed_value.ty;4350 new_decl.ty = typed_value.ty;
4340 new_decl.val = typed_value.val;4351 new_decl.val = typed_value.val;
4341 new_decl.has_tv = true;4352 new_decl.has_tv = true;
src/Sema.zig+47-29
...@@ -634,15 +634,19 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In...@@ -634,15 +634,19 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
634 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});634 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
635}635}
636636
637pub fn zirStructDecl(637pub fn analyzeStructDecl(
638 sema: *Sema,638 sema: *Sema,
639 block: *Scope.Block,639 block: *Scope.Block,
640 new_decl_arena: *std.heap.ArenaAllocator,
641 new_decl: *Decl,
640 inst: Zir.Inst.Index,642 inst: Zir.Inst.Index,
641 layout: std.builtin.TypeInfo.ContainerLayout,643 layout: std.builtin.TypeInfo.ContainerLayout,
642) InnerError!*Inst {644 struct_obj: *Module.Struct,
645) InnerError!void {
643 const tracy = trace(@src());646 const tracy = trace(@src());
644 defer tracy.end();647 defer tracy.end();
645648
649 const mod = sema.mod;
646 const gpa = sema.gpa;650 const gpa = sema.gpa;
647 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;651 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
648 const src = inst_data.src();652 const src = inst_data.src();
...@@ -650,27 +654,7 @@ pub fn zirStructDecl(...@@ -650,27 +654,7 @@ pub fn zirStructDecl(
650 const fields_len = extra.data.fields_len;654 const fields_len = extra.data.fields_len;
651 const decls_len = extra.data.decls_len;655 const decls_len = extra.data.decls_len;
652656
653 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);657 var extra_index: usize = try mod.scanNamespace(
654
655 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
656 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
657 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
658 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
659 .ty = Type.initTag(.type),
660 .val = struct_val,
661 });
662 struct_obj.* = .{
663 .owner_decl = sema.owner_decl,
664 .fields = .{},
665 .node_offset = inst_data.src_node,
666 .namespace = .{
667 .parent = sema.owner_decl.namespace,
668 .ty = struct_ty,
669 .file_scope = block.getFileScope(),
670 },
671 };
672
673 var extra_index: usize = try sema.mod.scanNamespace(
674 &struct_obj.namespace,658 &struct_obj.namespace,
675 extra.end,659 extra.end,
676 decls_len,660 decls_len,
...@@ -680,7 +664,7 @@ pub fn zirStructDecl(...@@ -680,7 +664,7 @@ pub fn zirStructDecl(
680 const body = sema.code.extra[extra_index..][0..extra.data.body_len];664 const body = sema.code.extra[extra_index..][0..extra.data.body_len];
681 if (fields_len == 0) {665 if (fields_len == 0) {
682 assert(body.len == 0);666 assert(body.len == 0);
683 return sema.analyzeDeclVal(block, src, new_decl);667 return;
684 }668 }
685669
686 try struct_obj.fields.ensureCapacity(&new_decl_arena.allocator, fields_len);670 try struct_obj.fields.ensureCapacity(&new_decl_arena.allocator, fields_len);
...@@ -691,7 +675,7 @@ pub fn zirStructDecl(...@@ -691,7 +675,7 @@ pub fn zirStructDecl(
691 // Within the field type, default value, and alignment expressions, the "owner decl"675 // Within the field type, default value, and alignment expressions, the "owner decl"
692 // should be the struct itself. Thus we need a new Sema.676 // should be the struct itself. Thus we need a new Sema.
693 var struct_sema: Sema = .{677 var struct_sema: Sema = .{
694 .mod = sema.mod,678 .mod = mod,
695 .gpa = gpa,679 .gpa = gpa,
696 .arena = &new_decl_arena.allocator,680 .arena = &new_decl_arena.allocator,
697 .code = sema.code,681 .code = sema.code,
...@@ -752,7 +736,7 @@ pub fn zirStructDecl(...@@ -752,7 +736,7 @@ pub fn zirStructDecl(
752 // This string needs to outlive the ZIR code.736 // This string needs to outlive the ZIR code.
753 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);737 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
754 if (field_type_ref == .none) {738 if (field_type_ref == .none) {
755 return sema.mod.fail(&block.base, src, "TODO: implement anytype struct field", .{});739 return mod.fail(&block.base, src, "TODO: implement anytype struct field", .{});
756 }740 }
757 const field_ty: Type = if (field_type_ref == .none)741 const field_ty: Type = if (field_type_ref == .none)
758 Type.initTag(.noreturn)742 Type.initTag(.noreturn)
...@@ -788,7 +772,38 @@ pub fn zirStructDecl(...@@ -788,7 +772,38 @@ pub fn zirStructDecl(
788 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;772 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
789 }773 }
790 }774 }
775}
776
777fn zirStructDecl(
778 sema: *Sema,
779 block: *Scope.Block,
780 inst: Zir.Inst.Index,
781 layout: std.builtin.TypeInfo.ContainerLayout,
782) InnerError!*Inst {
783 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
784 const src = inst_data.src();
785
786 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
791787
788 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
789 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
790 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
791 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{
792 .ty = Type.initTag(.type),
793 .val = struct_val,
794 });
795 struct_obj.* = .{
796 .owner_decl = sema.owner_decl,
797 .fields = .{},
798 .node_offset = inst_data.src_node,
799 .namespace = .{
800 .parent = sema.owner_decl.namespace,
801 .ty = struct_ty,
802 .file_scope = block.getFileScope(),
803 },
804 };
805 try sema.analyzeStructDecl(block, &new_decl_arena, new_decl, inst, layout, struct_obj);
806 try new_decl.finalizeNewArena(&new_decl_arena);
792 return sema.analyzeDeclVal(block, src, new_decl);807 return sema.analyzeDeclVal(block, src, new_decl);
793}808}
794809
...@@ -822,14 +837,14 @@ fn zirEnumDecl(...@@ -822,14 +837,14 @@ fn zirEnumDecl(
822 };837 };
823838
824 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);839 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);
825 const enum_ty_payload = try gpa.create(Type.Payload.EnumFull);840 const enum_ty_payload = try new_decl_arena.allocator.create(Type.Payload.EnumFull);
826 enum_ty_payload.* = .{841 enum_ty_payload.* = .{
827 .base = .{ .tag = if (nonexhaustive) .enum_nonexhaustive else .enum_full },842 .base = .{ .tag = if (nonexhaustive) .enum_nonexhaustive else .enum_full },
828 .data = enum_obj,843 .data = enum_obj,
829 };844 };
830 const enum_ty = Type.initPayload(&enum_ty_payload.base);845 const enum_ty = Type.initPayload(&enum_ty_payload.base);
831 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);846 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
832 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{847 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{
833 .ty = Type.initTag(.type),848 .ty = Type.initTag(.type),
834 .val = enum_val,849 .val = enum_val,
835 });850 });
...@@ -856,6 +871,7 @@ fn zirEnumDecl(...@@ -856,6 +871,7 @@ fn zirEnumDecl(
856 const body = sema.code.extra[extra_index..][0..extra.data.body_len];871 const body = sema.code.extra[extra_index..][0..extra.data.body_len];
857 if (fields_len == 0) {872 if (fields_len == 0) {
858 assert(body.len == 0);873 assert(body.len == 0);
874 try new_decl.finalizeNewArena(&new_decl_arena);
859 return sema.analyzeDeclVal(block, src, new_decl);875 return sema.analyzeDeclVal(block, src, new_decl);
860 }876 }
861877
...@@ -942,6 +958,7 @@ fn zirEnumDecl(...@@ -942,6 +958,7 @@ fn zirEnumDecl(
942 }958 }
943 }959 }
944960
961 try new_decl.finalizeNewArena(&new_decl_arena);
945 return sema.analyzeDeclVal(block, src, new_decl);962 return sema.analyzeDeclVal(block, src, new_decl);
946}963}
947964
...@@ -1424,10 +1441,11 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*In...@@ -1424,10 +1441,11 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*In
1424 const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len);1441 const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len);
1425 const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes);1442 const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes);
14261443
1427 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{1444 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{
1428 .ty = decl_ty,1445 .ty = decl_ty,
1429 .val = decl_val,1446 .val = decl_val,
1430 });1447 });
1448 try new_decl.finalizeNewArena(&new_decl_arena);
1431 return sema.analyzeDeclRef(block, .unneeded, new_decl);1449 return sema.analyzeDeclRef(block, .unneeded, new_decl);
1432}1450}
14331451
src/value.zig+8
...@@ -593,6 +593,14 @@ pub const Value = extern union {...@@ -593,6 +593,14 @@ pub const Value = extern union {
593 unreachable;593 unreachable;
594 }594 }
595595
596 /// Returns null if not a type or if the type has no namespace.
597 pub fn getTypeNamespace(self: Value) ?*Module.Scope.Namespace {
598 return switch (self.tag()) {
599 .ty => self.castTag(.ty).?.data.getNamespace(),
600 else => null,
601 };
602 }
603
596 /// Asserts that the value is representable as a type.604 /// Asserts that the value is representable as a type.
597 pub fn toType(self: Value, allocator: *Allocator) !Type {605 pub fn toType(self: Value, allocator: *Allocator) !Type {
598 return switch (self.tag()) {606 return switch (self.tag()) {