@@ -23,8 +23,8 @@ use rustc_middle::metadata::ModChild;
2323use rustc_middle:: ty:: Feed ;
2424use rustc_middle:: { bug, ty} ;
2525use rustc_span:: hygiene:: { ExpnId , LocalExpnId , MacroKind } ;
26- use rustc_span:: { Ident , Span , Symbol , kw, sym} ;
27- use tracing:: debug;
26+ use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , kw, sym} ;
27+ use tracing:: { debug, instrument } ;
2828
2929use crate :: Namespace :: { MacroNS , TypeNS , ValueNS } ;
3030use crate :: def_collector:: collect_definitions;
@@ -70,6 +70,7 @@ impl<'ra, Id: Into<DefId>> ToNameBinding<'ra> for (Res, ty::Visibility<Id>, Span
7070impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
7171 /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
7272 /// otherwise, reports an error.
73+ #[ instrument( level = "debug" , skip( self , def) ) ]
7374 pub ( crate ) fn define < T > ( & mut self , parent : Module < ' ra > , ident : Ident , ns : Namespace , def : T )
7475 where
7576 T : ToNameBinding < ' ra > ,
@@ -118,6 +119,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
118119 return module. copied ( ) ;
119120 }
120121
122+ //if def_id.is_crate_root() && !def_id.is_local() {
123+ // bug!(
124+ // "expected module for external crate {:?} to be created via `create_module_for_external_crate`",
125+ // def_id
126+ // );
127+ //}
128+
121129 if !def_id. is_local ( ) {
122130 // Query `def_kind` is not used because query system overhead is too expensive here.
123131 let def_kind = self . cstore ( ) . def_kind_untracked ( def_id) ;
@@ -143,6 +151,52 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
143151 None
144152 }
145153
154+ /// Creates `Module` instance for an external crate.
155+ /// `Module`s are usually created via `get_module`, but namespaced crates depend
156+ /// on the crate name passed via `--extern`, whereas `get_module` uses the metadata's
157+ /// crate name. We need a way to pass that name to a `Module` and this method does that.
158+ #[ instrument( level = "debug" , skip( self ) ) ]
159+ pub ( crate ) fn create_module_for_external_crate (
160+ & mut self ,
161+ def_id : DefId ,
162+ ident : Ident ,
163+ finalize : bool ,
164+ ) -> Module < ' ra > {
165+ if let Some ( module) = self . module_map . get ( & def_id) {
166+ return * module;
167+ }
168+
169+ if finalize {
170+ self . crate_loader ( |c| c. process_path_extern ( ident. name , ident. span ) ) ;
171+ }
172+
173+ let def_kind = self . cstore ( ) . def_kind_untracked ( def_id) ;
174+ match def_kind {
175+ DefKind :: Mod => {
176+ let parent = self
177+ . tcx
178+ . opt_parent ( def_id)
179+ . map ( |parent_id| self . get_nearest_non_block_module ( parent_id) ) ;
180+ // Query `expn_that_defined` is not used because
181+ // hashing spans in its result is expensive.
182+ let expn_id = self . cstore ( ) . expn_that_defined_untracked ( def_id, self . tcx . sess ) ;
183+ let module = self . new_module (
184+ parent,
185+ ModuleKind :: Def ( def_kind, def_id, Some ( ident. name ) ) ,
186+ expn_id,
187+ self . def_span ( def_id) ,
188+ // FIXME: Account for `#[no_implicit_prelude]` attributes.
189+ parent. is_some_and ( |module| module. no_implicit_prelude ) ,
190+ ) ;
191+
192+ return module;
193+ }
194+ _ => {
195+ bug ! ( "expected DefKind::Mod for external crate" ) ;
196+ }
197+ }
198+ }
199+
146200 pub ( crate ) fn expn_def_scope ( & mut self , expn_id : ExpnId ) -> Module < ' ra > {
147201 match expn_id. expn_data ( ) . macro_def_id {
148202 Some ( def_id) => self . macro_def_scope ( def_id) ,
@@ -196,7 +250,33 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
196250 visitor. parent_scope . macro_rules
197251 }
198252
253+ // Builds the reduced graph for an external crate.
254+ // It builds the graph for each child module of the crate and it also checks whether
255+ // namespaced crates with the same base name exist. If any exist it builds a graph for
256+ // each of those crates.
257+ #[ instrument( level = "debug" , skip( self ) ) ]
199258 pub ( crate ) fn build_reduced_graph_external ( & mut self , module : Module < ' ra > ) {
259+ // Check if `module`'s name is the base crate name for a namespaced crate
260+ // (i.e. `my_api` for the namespaced crates `my_api::utils` and `my_api::core`),
261+ // and process the extern crate for the namespaced crates if they exist.
262+ if let Some ( module_name) = module. kind . name ( ) {
263+ let namespace_crate_name = self
264+ . namespaced_crate_names
265+ . get ( module_name. as_str ( ) )
266+ . map ( |names| names. iter ( ) . map ( |s| s. to_string ( ) . clone ( ) ) . collect :: < Vec < String > > ( ) ) ;
267+
268+ if let Some ( namespaced_crate_names) = namespace_crate_name {
269+ debug ! ( ?namespaced_crate_names) ;
270+ for namespaced_crate_name in namespaced_crate_names {
271+ let parent_scope = ParentScope :: module ( module, self ) ;
272+ self . build_reduced_graph_for_namespaced_crate (
273+ & namespaced_crate_name,
274+ parent_scope,
275+ ) ;
276+ }
277+ }
278+ }
279+
200280 for child in self . tcx . module_children ( module. def_id ( ) ) {
201281 let parent_scope = ParentScope :: module ( module, self ) ;
202282 self . build_reduced_graph_for_external_crate_res ( child, parent_scope)
@@ -273,6 +353,43 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
273353 | Res :: Err => bug ! ( "unexpected resolution: {:?}" , res) ,
274354 }
275355 }
356+
357+ // Builds the reduced graph for a namespaced external crate (crate names like `foo::bar`).
358+ #[ instrument( level = "debug" , skip( self ) ) ]
359+ fn build_reduced_graph_for_namespaced_crate (
360+ & mut self ,
361+ name : & str ,
362+ parent_scope : ParentScope < ' ra > ,
363+ ) {
364+ let crate_id = self . crate_loader ( |c| {
365+ c. maybe_process_path_extern ( Symbol :: intern ( & name) )
366+ . expect ( & format ! ( "no crate_num for namespaced crate {}" , name) )
367+ } ) ;
368+
369+ let module = self . create_module_for_external_crate (
370+ crate_id. as_def_id ( ) ,
371+ Ident :: from_str ( name) ,
372+ false ,
373+ ) ;
374+ let ident = Ident :: from_str (
375+ name. split ( "::" ) . nth ( 1 ) . expect ( "namespaced crate name has unexpected form" ) ,
376+ ) ;
377+ let parent = parent_scope. module ;
378+ let res = module. res ( ) . expect ( "namespaced crate has no Res" ) . expect_non_local ( ) ;
379+ let expansion = parent_scope. expansion ;
380+
381+ match res {
382+ Res :: Def ( DefKind :: Mod , _) => {
383+ self . define (
384+ parent,
385+ ident,
386+ TypeNS ,
387+ ( module, ty:: Visibility :: < DefId > :: Public , DUMMY_SP , expansion) ,
388+ ) ;
389+ }
390+ _ => bug ! ( "expected namespaced crate to have Res Def(DefKind::Mod)" ) ,
391+ }
392+ }
276393}
277394
278395struct BuildReducedGraphVisitor < ' a , ' ra , ' tcx > {
@@ -469,6 +586,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
469586 }
470587 }
471588
589+ #[ instrument( level = "debug" , skip( self ) ) ]
472590 fn build_reduced_graph_for_use_tree (
473591 & mut self ,
474592 // This particular use tree
@@ -482,11 +600,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
482600 vis : ty:: Visibility ,
483601 root_span : Span ,
484602 ) {
485- debug ! (
486- "build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})" ,
487- parent_prefix, use_tree, nested
488- ) ;
489-
490603 // Top level use tree reuses the item's id and list stems reuse their parent
491604 // use tree's ids, so in both cases their visibilities are already filled.
492605 if nested && !list_stem {
@@ -589,7 +702,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
589702 let crate_root = self . r . resolve_crate_root ( source. ident ) ;
590703 let crate_name = match crate_root. kind {
591704 ModuleKind :: Def ( .., name) => name,
592- ModuleKind :: Block => unreachable ! ( ) ,
705+ ModuleKind :: Block | ModuleKind :: NamespaceCrate ( .. ) => unreachable ! ( ) ,
593706 } ;
594707 // HACK(eddyb) unclear how good this is, but keeping `$crate`
595708 // in `source` breaks `tests/ui/imports/import-crate-var.rs`,
@@ -897,6 +1010,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
8971010 }
8981011 }
8991012
1013+ #[ instrument( level = "debug" , skip( self ) ) ]
9001014 fn build_reduced_graph_for_extern_crate (
9011015 & mut self ,
9021016 orig_name : Option < Symbol > ,
@@ -922,7 +1036,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
9221036 } ) ;
9231037 crate_id. map ( |crate_id| {
9241038 self . r . extern_crate_map . insert ( local_def_id, crate_id) ;
925- self . r . expect_module ( crate_id. as_def_id ( ) )
1039+ self . r . create_module_for_external_crate ( crate_id. as_def_id ( ) , ident , false )
9261040 } )
9271041 }
9281042 . map ( |module| {
0 commit comments