@@ -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`.
@@ -4690,6 +4741,7 @@ pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_
4690
4741
pub const ImportFileResult = struct {
4691
4742
file : * File ,
4692
4743
is_new : bool ,
4744
+ is_pkg : bool ,
4693
4745
};
4694
4746
4695
4747
pub fn importPkg (mod : * Module , pkg : * Package ) ! ImportFileResult {
@@ -4709,6 +4761,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
4709
4761
if (gop .found_existing ) return ImportFileResult {
4710
4762
.file = gop .value_ptr .* ,
4711
4763
.is_new = false ,
4764
+ .is_pkg = true ,
4712
4765
};
4713
4766
4714
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
4785
.pkg = pkg ,
4733
4786
.root_decl = .none ,
4734
4787
};
4788
+ try new_file .addReference (mod .* , .{ .root = pkg });
4735
4789
return ImportFileResult {
4736
4790
.file = new_file ,
4737
4791
.is_new = true ,
4792
+ .is_pkg = true ,
4738
4793
};
4739
4794
}
4740
4795
@@ -4775,6 +4830,7 @@ pub fn importFile(
4775
4830
if (gop .found_existing ) return ImportFileResult {
4776
4831
.file = gop .value_ptr .* ,
4777
4832
.is_new = false ,
4833
+ .is_pkg = false ,
4778
4834
};
4779
4835
4780
4836
const new_file = try gpa .create (File );
@@ -4820,6 +4876,7 @@ pub fn importFile(
4820
4876
return ImportFileResult {
4821
4877
.file = new_file ,
4822
4878
.is_new = true ,
4879
+ .is_pkg = false ,
4823
4880
};
4824
4881
}
4825
4882
0 commit comments