diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-05-18 12:35:36 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-05-18 12:35:36 -0700 |
| commit | ab8f8465a301ded54d2a2504ca3394ec1425cacb (patch) | |
| tree | 60c94fd3f2695db767fc72bdf7e9528d788428cc /src/Compilation.zig | |
| parent | 4187008b5ed3118d9cf58dbdff8bad2974a7910d (diff) | |
| download | zig-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.zig | 12 |
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(); |
