Commit 7ef5938450

Martin Wickham <spexguy070@gmail.com>
2021-10-01 04:41:24
Fix decl removal from namespace when destroyed
1 parent b1e5081
Changed files (2)
src/Module.zig
@@ -1695,7 +1695,7 @@ pub const Scope = struct {
                     .ty = ty,
                     .val = val,
                 });
-                errdefer wad.block.sema.mod.deleteAnonDecl(&wad.block.base, new_decl);
+                errdefer wad.block.sema.mod.abortAnonDecl(new_decl);
                 try new_decl.finalizeNewArena(&wad.new_decl_arena);
                 wad.finished = true;
                 return new_decl;
@@ -4013,9 +4013,10 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void {
         },
     }
 
-    const dependants = decl.dependants.keys();
-    assert(dependants[0].namespace.anon_decls.swapRemove(decl));
+    const owner_namespace = if (decl.namespace.getDecl() == decl and decl.namespace.parent != null) decl.namespace.parent.? else decl.namespace;
+    assert(owner_namespace.anon_decls.swapRemove(decl));
 
+    const dependants = decl.dependants.keys();
     for (dependants) |dep| {
         dep.removeDependency(decl);
     }
@@ -4026,10 +4027,11 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void {
     decl.destroy(mod);
 }
 
-pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
-    log.debug("deleteAnonDecl {*} ({s})", .{ decl, decl.name });
-    const scope_decl = scope.srcDecl().?;
-    assert(scope_decl.namespace.anon_decls.swapRemove(decl));
+pub fn abortAnonDecl(mod: *Module, decl: *Decl) void {
+    log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name });
+    assert(decl.namespace.anon_decls.swapRemove(decl));
+    assert(decl.dependants.count() == 0);
+    assert(decl.dependencies.count() == 0);
     decl.destroy(mod);
 }
 
src/Sema.zig
@@ -1074,7 +1074,7 @@ fn zirStructDecl(
         .val = struct_val,
     }, type_name);
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
     struct_obj.* = .{
         .owner_decl = new_decl,
         .fields = .{},
@@ -1185,7 +1185,7 @@ fn zirEnumDecl(
         .val = enum_val,
     }, type_name);
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
 
     enum_obj.* = .{
         .owner_decl = new_decl,
@@ -1373,7 +1373,7 @@ fn zirUnionDecl(
         .val = union_val,
     }, type_name);
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
     union_obj.* = .{
         .owner_decl = new_decl,
         .tag_ty = Type.initTag(.@"null"),
@@ -1443,7 +1443,7 @@ fn zirErrorSetDecl(
         .val = error_set_val,
     }, type_name);
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
     const names = try new_decl_arena.allocator.alloc([]const u8, fields.len);
     for (fields) |str_index, i| {
         names[i] = try new_decl_arena.allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
@@ -2101,7 +2101,7 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A
         .ty = decl_ty,
         .val = decl_val,
     });
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
     try new_decl.finalizeNewArena(&new_decl_arena);
     return sema.analyzeDeclRef(new_decl);
 }
@@ -11804,7 +11804,7 @@ pub fn resolveDeclFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty:
     switch (ty.tag()) {
         .@"struct" => {
             const struct_obj = ty.castTag(.@"struct").?.data;
-            if (struct_obj.owner_decl.namespace.parent != sema.owner_decl.namespace) return;
+            if (struct_obj.owner_decl.namespace.parent != block.src_decl.namespace) return;
             switch (struct_obj.status) {
                 .none => {},
                 .field_types_wip => {
@@ -11822,7 +11822,7 @@ pub fn resolveDeclFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty:
         },
         .@"union", .union_tagged => {
             const union_obj = ty.cast(Type.Payload.Union).?.data;
-            if (union_obj.owner_decl.namespace.parent != sema.owner_decl.namespace) return;
+            if (union_obj.owner_decl.namespace.parent != block.src_decl.namespace) return;
             switch (union_obj.status) {
                 .none => {},
                 .field_types_wip => {
@@ -12210,7 +12210,7 @@ fn generateUnionTagTypeNumbered(
         .val = enum_val,
     });
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
 
     enum_obj.* = .{
         .owner_decl = new_decl,
@@ -12246,7 +12246,7 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Scope.Block, fields_len: u32)
         .val = enum_val,
     });
     new_decl.owns_tv = true;
-    errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
+    errdefer sema.mod.abortAnonDecl(new_decl);
 
     enum_obj.* = .{
         .owner_decl = new_decl,