| ... | @@ -1943,6 +1943,10 @@ pub const File = struct { | ... | @@ -1943,6 +1943,10 @@ pub const File = struct { |
| 1943 | zir: Zir, | 1943 | zir: Zir, |
| 1944 | /// Package that this file is a part of, managed externally. | 1944 | /// Package that this file is a part of, managed externally. |
| 1945 | pkg: *Package, | 1945 | pkg: *Package, |
| | 1946 | /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen. |
| | 1947 | multi_pkg: bool = false, |
| | 1948 | /// List of references to this file, used for multi-package errors. |
| | 1949 | references: std.ArrayListUnmanaged(Reference) = .{}, |
| 1946 | | 1950 | |
| 1947 | /// Used by change detection algorithm, after astgen, contains the | 1951 | /// Used by change detection algorithm, after astgen, contains the |
| 1948 | /// set of decls that existed in the previous ZIR but not in the new one. | 1952 | /// set of decls that existed in the previous ZIR but not in the new one. |
| ... | @@ -1958,6 +1962,14 @@ pub const File = struct { | ... | @@ -1958,6 +1962,14 @@ pub const File = struct { |
| 1958 | /// successful, this field is unloaded. | 1962 | /// successful, this field is unloaded. |
| 1959 | prev_zir: ?*Zir = null, | 1963 | prev_zir: ?*Zir = null, |
| 1960 | | 1964 | |
| | 1965 | /// A single reference to a file. |
| | 1966 | const Reference = union(enum) { |
| | 1967 | /// The file is imported directly (i.e. not as a package) with @import. |
| | 1968 | import: SrcLoc, |
| | 1969 | /// The file is the root of a package. |
| | 1970 | root: *Package, |
| | 1971 | }; |
| | 1972 | |
| 1961 | pub fn unload(file: *File, gpa: Allocator) void { | 1973 | pub fn unload(file: *File, gpa: Allocator) void { |
| 1962 | file.unloadTree(gpa); | 1974 | file.unloadTree(gpa); |
| 1963 | file.unloadSource(gpa); | 1975 | file.unloadSource(gpa); |
| ... | @@ -1990,6 +2002,7 @@ pub const File = struct { | ... | @@ -1990,6 +2002,7 @@ pub const File = struct { |
| 1990 | log.debug("deinit File {s}", .{file.sub_file_path}); | 2002 | log.debug("deinit File {s}", .{file.sub_file_path}); |
| 1991 | file.deleted_decls.deinit(gpa); | 2003 | file.deleted_decls.deinit(gpa); |
| 1992 | file.outdated_decls.deinit(gpa); | 2004 | file.outdated_decls.deinit(gpa); |
| | 2005 | file.references.deinit(gpa); |
| 1993 | if (file.root_decl.unwrap()) |root_decl| { | 2006 | if (file.root_decl.unwrap()) |root_decl| { |
| 1994 | mod.destroyDecl(root_decl); | 2007 | mod.destroyDecl(root_decl); |
| 1995 | } | 2008 | } |
| ... | @@ -2110,6 +2123,44 @@ pub const File = struct { | ... | @@ -2110,6 +2123,44 @@ pub const File = struct { |
| 2110 | else => true, | 2123 | else => true, |
| 2111 | }; | 2124 | }; |
| 2112 | } | 2125 | } |
| | 2126 | |
| | 2127 | /// Add a reference to this file during AstGen. |
| | 2128 | pub fn addReference(file: *File, mod: Module, ref: Reference) !void { |
| | 2129 | try file.references.append(mod.gpa, ref); |
| | 2130 | |
| | 2131 | const pkg = switch (ref) { |
| | 2132 | .import => |loc| loc.file_scope.pkg, |
| | 2133 | .root => |pkg| pkg, |
| | 2134 | }; |
| | 2135 | if (pkg != file.pkg) file.multi_pkg = true; |
| | 2136 | } |
| | 2137 | |
| | 2138 | /// Mark this file and every file referenced by it as multi_pkg and report an |
| | 2139 | /// astgen_failure error for them. AstGen must have completed in its entirety. |
| | 2140 | pub fn recursiveMarkMultiPkg(file: *File, mod: *Module) void { |
| | 2141 | file.multi_pkg = true; |
| | 2142 | file.status = .astgen_failure; |
| | 2143 | |
| | 2144 | std.debug.assert(file.zir_loaded); |
| | 2145 | const imports_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.imports)]; |
| | 2146 | if (imports_index == 0) return; |
| | 2147 | const extra = file.zir.extraData(Zir.Inst.Imports, imports_index); |
| | 2148 | |
| | 2149 | var import_i: u32 = 0; |
| | 2150 | var extra_index = extra.end; |
| | 2151 | while (import_i < extra.data.imports_len) : (import_i += 1) { |
| | 2152 | const item = file.zir.extraData(Zir.Inst.Imports.Item, extra_index); |
| | 2153 | extra_index = item.end; |
| | 2154 | |
| | 2155 | const import_path = file.zir.nullTerminatedString(item.data.name); |
| | 2156 | if (mem.eql(u8, import_path, "builtin")) continue; |
| | 2157 | |
| | 2158 | const res = mod.importFile(file, import_path) catch continue; |
| | 2159 | if (!res.is_pkg and !res.file.multi_pkg) { |
| | 2160 | res.file.recursiveMarkMultiPkg(mod); |
| | 2161 | } |
| | 2162 | } |
| | 2163 | } |
| 2113 | }; | 2164 | }; |
| 2114 | | 2165 | |
| 2115 | /// Represents the contents of a file loaded with `@embedFile`. | 2166 | /// Represents the contents of a file loaded with `@embedFile`. |
| ... | @@ -4690,6 +4741,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_ | ... | @@ -4690,6 +4741,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_ |
| 4690 | pub const ImportFileResult = struct { | 4741 | pub const ImportFileResult = struct { |
| 4691 | file: *File, | 4742 | file: *File, |
| 4692 | is_new: bool, | 4743 | is_new: bool, |
| | 4744 | is_pkg: bool, |
| 4693 | }; | 4745 | }; |
| 4694 | | 4746 | |
| 4695 | pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { | 4747 | pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| ... | @@ -4709,6 +4761,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { | ... | @@ -4709,6 +4761,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| 4709 | if (gop.found_existing) return ImportFileResult{ | 4761 | if (gop.found_existing) return ImportFileResult{ |
| 4710 | .file = gop.value_ptr.*, | 4762 | .file = gop.value_ptr.*, |
| 4711 | .is_new = false, | 4763 | .is_new = false, |
| | 4764 | .is_pkg = true, |
| 4712 | }; | 4765 | }; |
| 4713 | | 4766 | |
| 4714 | const sub_file_path = try gpa.dupe(u8, pkg.root_src_path); | 4767 | const sub_file_path = try gpa.dupe(u8, pkg.root_src_path); |
| ... | @@ -4732,9 +4785,11 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { | ... | @@ -4732,9 +4785,11 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| 4732 | .pkg = pkg, | 4785 | .pkg = pkg, |
| 4733 | .root_decl = .none, | 4786 | .root_decl = .none, |
| 4734 | }; | 4787 | }; |
| | 4788 | try new_file.addReference(mod.*, .{ .root = pkg }); |
| 4735 | return ImportFileResult{ | 4789 | return ImportFileResult{ |
| 4736 | .file = new_file, | 4790 | .file = new_file, |
| 4737 | .is_new = true, | 4791 | .is_new = true, |
| | 4792 | .is_pkg = true, |
| 4738 | }; | 4793 | }; |
| 4739 | } | 4794 | } |
| 4740 | | 4795 | |
| ... | @@ -4775,6 +4830,7 @@ pub fn importFile( | ... | @@ -4775,6 +4830,7 @@ pub fn importFile( |
| 4775 | if (gop.found_existing) return ImportFileResult{ | 4830 | if (gop.found_existing) return ImportFileResult{ |
| 4776 | .file = gop.value_ptr.*, | 4831 | .file = gop.value_ptr.*, |
| 4777 | .is_new = false, | 4832 | .is_new = false, |
| | 4833 | .is_pkg = false, |
| 4778 | }; | 4834 | }; |
| 4779 | | 4835 | |
| 4780 | const new_file = try gpa.create(File); | 4836 | const new_file = try gpa.create(File); |
| ... | @@ -4820,6 +4876,7 @@ pub fn importFile( | ... | @@ -4820,6 +4876,7 @@ pub fn importFile( |
| 4820 | return ImportFileResult{ | 4876 | return ImportFileResult{ |
| 4821 | .file = new_file, | 4877 | .file = new_file, |
| 4822 | .is_new = true, | 4878 | .is_new = true, |
| | 4879 | .is_pkg = false, |
| 4823 | }; | 4880 | }; |
| 4824 | } | 4881 | } |
| 4825 | | 4882 | |