aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-05-18 12:35:36 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-05-18 12:35:36 -0700
commitab8f8465a301ded54d2a2504ca3394ec1425cacb (patch)
tree60c94fd3f2695db767fc72bdf7e9528d788428cc /src/Compilation.zig
parent4187008b5ed3118d9cf58dbdff8bad2974a7910d (diff)
downloadzig-ab8f8465a301ded54d2a2504ca3394ec1425cacb.tar.gz
zig-ab8f8465a301ded54d2a2504ca3394ec1425cacb.zip
stage2: fix deletion of Decls that get re-referenced
When scanDecls happens, we create stub Decl objects that have not been semantically analyzed. When they get referenced, they get semantically analyzed. Before this commit, when they got unreferenced, they were completely deleted, including deleted from the containing Namespace. However, if the update did not cause the containing Namespace to get deleted, for example, if `std.builtin.ExportOptions` is no longer referenced, but `std.builtin` is still referenced, and then `ExportOptions` gets referenced again, the Namespace would be incorrectly missing the Decl, so we get an incorrect "no such member" error. The solution is to, when dealing with a no longer referenced Decl objects during an update, clear them to the state they would be in on a fresh scanDecl, rather than completely deleting them.
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index a5c365fa40..0b77d8ee02 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1620,13 +1620,21 @@ pub fn update(self: *Compilation) !void {
if (!use_stage1) {
if (self.bin_file.options.module) |module| {
// Process the deletion set. We use a while loop here because the
- // deletion set may grow as we call `deleteDecl` within this loop,
+ // deletion set may grow as we call `clearDecl` within this loop,
// and more unreferenced Decls are revealed.
while (module.deletion_set.entries.items.len != 0) {
const decl = module.deletion_set.entries.items[0].key;
assert(decl.deletion_flag);
assert(decl.dependants.count() == 0);
- try module.deleteDecl(decl, null);
+ const is_anon = if (decl.zir_decl_index == 0) blk: {
+ break :blk decl.namespace.anon_decls.swapRemove(decl) != null;
+ } else false;
+
+ try module.clearDecl(decl, null);
+
+ if (is_anon) {
+ decl.destroy(module);
+ }
}
try module.processExports();