@@ -1943,6 +1943,10 @@ pub const File = struct {
1943
1943
zir : Zir ,
1944
1944
/// Package that this file is a part of, managed externally.
1945
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
1951
/// Used by change detection algorithm, after astgen, contains the
1948
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
1962
/// successful, this field is unloaded.
1959
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
1973
pub fn unload (file : * File , gpa : Allocator ) void {
1962
1974
file .unloadTree (gpa );
1963
1975
file .unloadSource (gpa );
@@ -1990,6 +2002,7 @@ pub const File = struct {
1990
2002
log .debug ("deinit File {s}" , .{file .sub_file_path });
1991
2003
file .deleted_decls .deinit (gpa );
1992
2004
file .outdated_decls .deinit (gpa );
2005
+ file .references .deinit (gpa );
1993
2006
if (file .root_decl .unwrap ()) | root_decl | {
1994
2007
mod .destroyDecl (root_decl );
1995
2008
}
@@ -2110,6 +2123,44 @@ pub const File = struct {
2110
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
2166
/// Represents the contents of a file loaded with `@embedFile`.
@@ -4695,6 +4746,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_
4695
4746
pub const ImportFileResult = struct {
4696
4747
file : * File ,
4697
4748
is_new : bool ,
4749
+ is_pkg : bool ,
4698
4750
};
4699
4751
4700
4752
pub fn importPkg (mod : * Module , pkg : * Package ) ! ImportFileResult {
@@ -4714,6 +4766,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4714
4766
if (gop .found_existing ) return ImportFileResult {
4715
4767
.file = gop .value_ptr .* ,
4716
4768
.is_new = false ,
4769
+ .is_pkg = true ,
4717
4770
};
4718
4771
4719
4772
const sub_file_path = try gpa .dupe (u8 , pkg .root_src_path );
@@ -4737,9 +4790,11 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4737
4790
.pkg = pkg ,
4738
4791
.root_decl = .none ,
4739
4792
};
4793
+ try new_file .addReference (mod .* , .{ .root = pkg });
4740
4794
return ImportFileResult {
4741
4795
.file = new_file ,
4742
4796
.is_new = true ,
4797
+ .is_pkg = true ,
4743
4798
};
4744
4799
}
4745
4800
@@ -4780,6 +4835,7 @@ pub fn importFile(
4780
4835
if (gop .found_existing ) return ImportFileResult {
4781
4836
.file = gop .value_ptr .* ,
4782
4837
.is_new = false ,
4838
+ .is_pkg = false ,
4783
4839
};
4784
4840
4785
4841
const new_file = try gpa .create (File );
@@ -4825,6 +4881,7 @@ pub fn importFile(
4825
4881
return ImportFileResult {
4826
4882
.file = new_file ,
4827
4883
.is_new = true ,
4884
+ .is_pkg = false ,
4828
4885
};
4829
4886
}
4830
4887
0 commit comments