@@ -1895,6 +1895,10 @@ pub const File = struct {
1895
1895
zir : Zir ,
1896
1896
/// Package that this file is a part of, managed externally.
1897
1897
pkg : * Package ,
1898
+ /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.
1899
+ multi_pkg : bool = false ,
1900
+ /// List of references to this file, used for multi-package errors.
1901
+ references : std .ArrayListUnmanaged (Reference ) = .{},
1898
1902
1899
1903
/// Used by change detection algorithm, after astgen, contains the
1900
1904
/// set of decls that existed in the previous ZIR but not in the new one.
@@ -1910,6 +1914,14 @@ pub const File = struct {
1910
1914
/// successful, this field is unloaded.
1911
1915
prev_zir : ? * Zir = null ,
1912
1916
1917
+ /// A single reference to a file.
1918
+ const Reference = union (enum ) {
1919
+ /// The file is imported directly (i.e. not as a package) with @import.
1920
+ import : SrcLoc ,
1921
+ /// The file is the root of a package.
1922
+ root : * Package ,
1923
+ };
1924
+
1913
1925
pub fn unload (file : * File , gpa : Allocator ) void {
1914
1926
file .unloadTree (gpa );
1915
1927
file .unloadSource (gpa );
@@ -1942,6 +1954,7 @@ pub const File = struct {
1942
1954
log .debug ("deinit File {s}" , .{file .sub_file_path });
1943
1955
file .deleted_decls .deinit (gpa );
1944
1956
file .outdated_decls .deinit (gpa );
1957
+ file .references .deinit (gpa );
1945
1958
if (file .root_decl .unwrap ()) | root_decl | {
1946
1959
mod .destroyDecl (root_decl );
1947
1960
}
@@ -2062,6 +2075,44 @@ pub const File = struct {
2062
2075
else = > true ,
2063
2076
};
2064
2077
}
2078
+
2079
+ /// Add a reference to this file during AstGen.
2080
+ pub fn addReference (file : * File , mod : Module , ref : Reference ) ! void {
2081
+ try file .references .append (mod .gpa , ref );
2082
+
2083
+ const pkg = switch (ref ) {
2084
+ .import = > | loc | loc .file_scope .pkg ,
2085
+ .root = > | pkg | pkg ,
2086
+ };
2087
+ if (pkg != file .pkg ) file .multi_pkg = true ;
2088
+ }
2089
+
2090
+ /// Mark this file and every file referenced by it as multi_pkg and report an
2091
+ /// astgen_failure error for them. AstGen must have completed in its entirety.
2092
+ pub fn recursiveMarkMultiPkg (file : * File , mod : * Module ) void {
2093
+ file .multi_pkg = true ;
2094
+ file .status = .astgen_failure ;
2095
+
2096
+ std .debug .assert (file .zir_loaded );
2097
+ const imports_index = file .zir .extra [@enumToInt (Zir .ExtraIndex .imports )];
2098
+ if (imports_index == 0 ) return ;
2099
+ const extra = file .zir .extraData (Zir .Inst .Imports , imports_index );
2100
+
2101
+ var import_i : u32 = 0 ;
2102
+ var extra_index = extra .end ;
2103
+ while (import_i < extra .data .imports_len ) : (import_i += 1 ) {
2104
+ const item = file .zir .extraData (Zir .Inst .Imports .Item , extra_index );
2105
+ extra_index = item .end ;
2106
+
2107
+ const import_path = file .zir .nullTerminatedString (item .data .name );
2108
+ if (mem .eql (u8 , import_path , "builtin" )) continue ;
2109
+
2110
+ const res = mod .importFile (file , import_path ) catch continue ;
2111
+ if (res .is_file and ! res .file .multi_pkg ) {
2112
+ res .file .recursiveMarkMultiPkg (mod );
2113
+ }
2114
+ }
2115
+ }
2065
2116
};
2066
2117
2067
2118
/// Represents the contents of a file loaded with `@embedFile`.
@@ -4867,6 +4918,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_
4867
4918
pub const ImportFileResult = struct {
4868
4919
file : * File ,
4869
4920
is_new : bool ,
4921
+ is_file : bool ,
4870
4922
};
4871
4923
4872
4924
pub fn importPkg (mod : * Module , pkg : * Package ) ! ImportFileResult {
@@ -4886,6 +4938,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4886
4938
if (gop .found_existing ) return ImportFileResult {
4887
4939
.file = gop .value_ptr .* ,
4888
4940
.is_new = false ,
4941
+ .is_file = false ,
4889
4942
};
4890
4943
4891
4944
const sub_file_path = try gpa .dupe (u8 , pkg .root_src_path );
@@ -4909,9 +4962,11 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4909
4962
.pkg = pkg ,
4910
4963
.root_decl = .none ,
4911
4964
};
4965
+ try new_file .addReference (mod .* , .{ .root = pkg });
4912
4966
return ImportFileResult {
4913
4967
.file = new_file ,
4914
4968
.is_new = true ,
4969
+ .is_file = false ,
4915
4970
};
4916
4971
}
4917
4972
@@ -4952,6 +5007,7 @@ pub fn importFile(
4952
5007
if (gop .found_existing ) return ImportFileResult {
4953
5008
.file = gop .value_ptr .* ,
4954
5009
.is_new = false ,
5010
+ .is_file = true ,
4955
5011
};
4956
5012
4957
5013
const new_file = try gpa .create (File );
@@ -4997,6 +5053,7 @@ pub fn importFile(
4997
5053
return ImportFileResult {
4998
5054
.file = new_file ,
4999
5055
.is_new = true ,
5056
+ .is_file = true ,
5000
5057
};
5001
5058
}
5002
5059
0 commit comments