@@ -1892,6 +1892,10 @@ pub const File = struct {
1892
1892
zir : Zir ,
1893
1893
/// Package that this file is a part of, managed externally.
1894
1894
pkg : * Package ,
1895
+ /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.
1896
+ multi_pkg : bool = false ,
1897
+ /// List of references to this file, used for multi-package errors.
1898
+ references : std .ArrayListUnmanaged (Reference ) = .{},
1895
1899
1896
1900
/// Used by change detection algorithm, after astgen, contains the
1897
1901
/// set of decls that existed in the previous ZIR but not in the new one.
@@ -1907,6 +1911,14 @@ pub const File = struct {
1907
1911
/// successful, this field is unloaded.
1908
1912
prev_zir : ? * Zir = null ,
1909
1913
1914
+ /// A single reference to a file.
1915
+ const Reference = union (enum ) {
1916
+ /// The file is imported directly (i.e. not as a package) with @import.
1917
+ import : SrcLoc ,
1918
+ /// The file is the root of a package.
1919
+ root : * Package ,
1920
+ };
1921
+
1910
1922
pub fn unload (file : * File , gpa : Allocator ) void {
1911
1923
file .unloadTree (gpa );
1912
1924
file .unloadSource (gpa );
@@ -1939,6 +1951,7 @@ pub const File = struct {
1939
1951
log .debug ("deinit File {s}" , .{file .sub_file_path });
1940
1952
file .deleted_decls .deinit (gpa );
1941
1953
file .outdated_decls .deinit (gpa );
1954
+ file .references .deinit (gpa );
1942
1955
if (file .root_decl .unwrap ()) | root_decl | {
1943
1956
mod .destroyDecl (root_decl );
1944
1957
}
@@ -2059,6 +2072,44 @@ pub const File = struct {
2059
2072
else = > true ,
2060
2073
};
2061
2074
}
2075
+
2076
+ /// Add a reference to this file during AstGen.
2077
+ pub fn addReference (file : * File , mod : Module , ref : Reference ) ! void {
2078
+ try file .references .append (mod .gpa , ref );
2079
+
2080
+ const pkg = switch (ref ) {
2081
+ .import = > | loc | loc .file_scope .pkg ,
2082
+ .root = > | pkg | pkg ,
2083
+ };
2084
+ if (pkg != file .pkg ) file .multi_pkg = true ;
2085
+ }
2086
+
2087
+ /// Mark this file and every file referenced by it as multi_pkg and report an
2088
+ /// astgen_failure error for them. AstGen must have completed in its entirety.
2089
+ pub fn recursiveMarkMultiPkg (file : * File , mod : * Module ) void {
2090
+ file .multi_pkg = true ;
2091
+ file .status = .astgen_failure ;
2092
+
2093
+ std .debug .assert (file .zir_loaded );
2094
+ const imports_index = file .zir .extra [@enumToInt (Zir .ExtraIndex .imports )];
2095
+ if (imports_index == 0 ) return ;
2096
+ const extra = file .zir .extraData (Zir .Inst .Imports , imports_index );
2097
+
2098
+ var import_i : u32 = 0 ;
2099
+ var extra_index = extra .end ;
2100
+ while (import_i < extra .data .imports_len ) : (import_i += 1 ) {
2101
+ const item = file .zir .extraData (Zir .Inst .Imports .Item , extra_index );
2102
+ extra_index = item .end ;
2103
+
2104
+ const import_path = file .zir .nullTerminatedString (item .data .name );
2105
+ if (mem .eql (u8 , import_path , "builtin" )) continue ;
2106
+
2107
+ const res = mod .importFile (file , import_path ) catch continue ;
2108
+ if (res .is_file and ! res .file .multi_pkg ) {
2109
+ res .file .recursiveMarkMultiPkg (mod );
2110
+ }
2111
+ }
2112
+ }
2062
2113
};
2063
2114
2064
2115
/// Represents the contents of a file loaded with `@embedFile`.
@@ -4864,6 +4915,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_
4864
4915
pub const ImportFileResult = struct {
4865
4916
file : * File ,
4866
4917
is_new : bool ,
4918
+ is_file : bool ,
4867
4919
};
4868
4920
4869
4921
pub fn importPkg (mod : * Module , pkg : * Package ) ! ImportFileResult {
@@ -4883,6 +4935,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4883
4935
if (gop .found_existing ) return ImportFileResult {
4884
4936
.file = gop .value_ptr .* ,
4885
4937
.is_new = false ,
4938
+ .is_file = false ,
4886
4939
};
4887
4940
4888
4941
const sub_file_path = try gpa .dupe (u8 , pkg .root_src_path );
@@ -4906,9 +4959,11 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4906
4959
.pkg = pkg ,
4907
4960
.root_decl = .none ,
4908
4961
};
4962
+ try new_file .addReference (mod .* , .{ .root = pkg });
4909
4963
return ImportFileResult {
4910
4964
.file = new_file ,
4911
4965
.is_new = true ,
4966
+ .is_file = false ,
4912
4967
};
4913
4968
}
4914
4969
@@ -4949,6 +5004,7 @@ pub fn importFile(
4949
5004
if (gop .found_existing ) return ImportFileResult {
4950
5005
.file = gop .value_ptr .* ,
4951
5006
.is_new = false ,
5007
+ .is_file = true ,
4952
5008
};
4953
5009
4954
5010
const new_file = try gpa .create (File );
@@ -4990,6 +5046,7 @@ pub fn importFile(
4990
5046
return ImportFileResult {
4991
5047
.file = new_file ,
4992
5048
.is_new = true ,
5049
+ .is_file = true ,
4993
5050
};
4994
5051
}
4995
5052
0 commit comments