mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: more Decl lifetime fixes
* File stores `root_decl: Decl` instead of `namespace: *Namespace`. This maps more cleanly to the actual ownership, since the `File` does own the root decl, but it does not directly own the `Namespace`. * `semaFile` completes the creation of the `Decl` even when semantic analysis fails. The `analysis` field of the `Decl` will contain the results of semantic analysis. This prevents cleaning up of memory still referenced by other Decl objects. * `semaDecl` sets `Struct.zir_index` of the root struct decl, which fixes use of undefined value in case the first update contained a ZIR compile error.
This commit is contained in:
parent
1ab1a96f87
commit
71afc30880
@ -822,7 +822,7 @@ pub const Scope = struct {
|
||||
pub fn namespace(scope: *Scope) *Namespace {
|
||||
switch (scope.tag) {
|
||||
.block => return scope.cast(Block).?.sema.owner_decl.namespace,
|
||||
.file => return scope.cast(File).?.namespace.?,
|
||||
.file => return scope.cast(File).?.root_decl.?.namespace,
|
||||
.namespace => return scope.cast(Namespace).?,
|
||||
.decl_ref => return scope.cast(DeclRef).?.decl.namespace,
|
||||
}
|
||||
@ -998,10 +998,8 @@ pub const Scope = struct {
|
||||
zir: Zir,
|
||||
/// Package that this file is a part of, managed externally.
|
||||
pkg: *Package,
|
||||
/// The namespace of the struct that represents this file.
|
||||
/// Populated only when `have_decl` is true.
|
||||
/// Owned by its owner Decl Value.
|
||||
namespace: ?*Namespace,
|
||||
/// The Decl of the struct that represents this File.
|
||||
root_decl: ?*Decl,
|
||||
|
||||
/// Used by change detection algorithm, after astgen, contains the
|
||||
/// set of decls that existed in the previous ZIR but not in the new one.
|
||||
@ -1049,8 +1047,8 @@ pub const Scope = struct {
|
||||
log.debug("deinit File {s}", .{file.sub_file_path});
|
||||
file.deleted_decls.deinit(gpa);
|
||||
file.outdated_decls.deinit(gpa);
|
||||
if (file.namespace) |ns| {
|
||||
ns.getDecl().destroy(mod);
|
||||
if (file.root_decl) |root_decl| {
|
||||
root_decl.destroy(mod);
|
||||
}
|
||||
gpa.free(file.sub_file_path);
|
||||
file.unload(gpa);
|
||||
@ -2576,11 +2574,11 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
|
||||
gpa.destroy(file_prev_zir);
|
||||
file.prev_zir = null;
|
||||
try updateZirRefs(gpa, file, prev_zir);
|
||||
} else if (file.namespace) |ns| {
|
||||
} else if (file.root_decl) |root_decl| {
|
||||
// First time the File has succeeded ZIR. We must mark it outdated since
|
||||
// we have already tried to semantically analyze it.
|
||||
try file.outdated_decls.resize(gpa, 1);
|
||||
file.outdated_decls.items[0] = ns.getDecl();
|
||||
file.outdated_decls.items[0] = root_decl;
|
||||
}
|
||||
} else {
|
||||
try updateZirRefs(gpa, file, prev_zir);
|
||||
@ -2626,7 +2624,7 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
|
||||
var decl_stack: std.ArrayListUnmanaged(*Decl) = .{};
|
||||
defer decl_stack.deinit(gpa);
|
||||
|
||||
const root_decl = file.namespace.?.getDecl();
|
||||
const root_decl = file.root_decl.?;
|
||||
try decl_stack.append(gpa, root_decl);
|
||||
|
||||
file.deleted_decls.clearRetainingCapacity();
|
||||
@ -2848,7 +2846,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (file.namespace != null) return;
|
||||
if (file.root_decl != null) return;
|
||||
|
||||
const gpa = mod.gpa;
|
||||
var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
|
||||
@ -2870,8 +2868,8 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
|
||||
.file_scope = file,
|
||||
},
|
||||
};
|
||||
file.namespace = &struct_obj.namespace;
|
||||
const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);
|
||||
file.root_decl = new_decl;
|
||||
struct_obj.owner_decl = new_decl;
|
||||
new_decl.src_line = 0;
|
||||
new_decl.name = try file.fullyQualifiedNameZ(gpa);
|
||||
@ -2917,9 +2915,12 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
|
||||
};
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
try sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj);
|
||||
|
||||
new_decl.analysis = .complete;
|
||||
if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
|
||||
new_decl.analysis = .complete;
|
||||
} else |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {},
|
||||
}
|
||||
} else {
|
||||
new_decl.analysis = .file_failure;
|
||||
}
|
||||
@ -2964,6 +2965,9 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
|
||||
log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
|
||||
const main_struct_inst = zir.getMainStruct();
|
||||
const struct_obj = decl.getStruct().?;
|
||||
// This might not have gotten set in `semaFile` if the first time had
|
||||
// a ZIR failure, so we set it here in case.
|
||||
struct_obj.zir_index = main_struct_inst;
|
||||
try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
|
||||
decl.analysis = .complete;
|
||||
decl.generation = mod.generation;
|
||||
@ -3165,7 +3169,7 @@ pub fn importPkg(mod: *Module, cur_pkg: *Package, pkg: *Package) !ImportFileResu
|
||||
.zir = undefined,
|
||||
.status = .never_loaded,
|
||||
.pkg = pkg,
|
||||
.namespace = null,
|
||||
.root_decl = null,
|
||||
};
|
||||
return ImportFileResult{
|
||||
.file = new_file,
|
||||
@ -3231,7 +3235,7 @@ pub fn importFile(
|
||||
.zir = undefined,
|
||||
.status = .never_loaded,
|
||||
.pkg = cur_file.pkg,
|
||||
.namespace = null,
|
||||
.root_decl = null,
|
||||
};
|
||||
return ImportFileResult{
|
||||
.file = new_file,
|
||||
|
||||
@ -4409,7 +4409,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
|
||||
},
|
||||
};
|
||||
try mod.semaFile(result.file);
|
||||
return mod.constType(sema.arena, src, result.file.namespace.?.ty);
|
||||
return mod.constType(sema.arena, src, result.file.root_decl.?.ty);
|
||||
}
|
||||
|
||||
fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
@ -7307,7 +7307,7 @@ fn getBuiltinType(
|
||||
const opt_builtin_inst = try sema.analyzeNamespaceLookup(
|
||||
block,
|
||||
src,
|
||||
std_file.namespace.?,
|
||||
std_file.root_decl.?.namespace,
|
||||
"builtin",
|
||||
);
|
||||
const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src);
|
||||
|
||||
@ -3656,7 +3656,7 @@ pub fn cmdAstgen(
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.pkg = undefined,
|
||||
.namespace = undefined,
|
||||
.root_decl = null,
|
||||
};
|
||||
|
||||
const source = try arena.allocSentinel(u8, stat.size, 0);
|
||||
@ -3766,7 +3766,7 @@ pub fn cmdChangelist(
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.pkg = undefined,
|
||||
.namespace = undefined,
|
||||
.root_decl = null,
|
||||
};
|
||||
|
||||
const source = try arena.allocSentinel(u8, stat.size, 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user