@@ -23,8 +23,8 @@ use rustc_middle::metadata::ModChild;
23
23
use rustc_middle:: ty:: Feed ;
24
24
use rustc_middle:: { bug, ty} ;
25
25
use 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 } ;
28
28
29
29
use crate :: Namespace :: { MacroNS , TypeNS , ValueNS } ;
30
30
use crate :: def_collector:: collect_definitions;
@@ -70,6 +70,7 @@ impl<'ra, Id: Into<DefId>> ToNameBinding<'ra> for (Res, ty::Visibility<Id>, Span
70
70
impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
71
71
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
72
72
/// otherwise, reports an error.
73
+ #[ instrument( level = "debug" , skip( self , def) ) ]
73
74
pub ( crate ) fn define < T > ( & mut self , parent : Module < ' ra > , ident : Ident , ns : Namespace , def : T )
74
75
where
75
76
T : ToNameBinding < ' ra > ,
@@ -118,6 +119,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
118
119
return module. copied ( ) ;
119
120
}
120
121
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
+
121
129
if !def_id. is_local ( ) {
122
130
// Query `def_kind` is not used because query system overhead is too expensive here.
123
131
let def_kind = self . cstore ( ) . def_kind_untracked ( def_id) ;
@@ -143,6 +151,52 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
143
151
None
144
152
}
145
153
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
+
146
200
pub ( crate ) fn expn_def_scope ( & mut self , expn_id : ExpnId ) -> Module < ' ra > {
147
201
match expn_id. expn_data ( ) . macro_def_id {
148
202
Some ( def_id) => self . macro_def_scope ( def_id) ,
@@ -196,7 +250,33 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
196
250
visitor. parent_scope . macro_rules
197
251
}
198
252
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 ) ) ]
199
258
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
+
200
280
for child in self . tcx . module_children ( module. def_id ( ) ) {
201
281
let parent_scope = ParentScope :: module ( module, self ) ;
202
282
self . build_reduced_graph_for_external_crate_res ( child, parent_scope)
@@ -273,6 +353,43 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
273
353
| Res :: Err => bug ! ( "unexpected resolution: {:?}" , res) ,
274
354
}
275
355
}
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
+ }
276
393
}
277
394
278
395
struct BuildReducedGraphVisitor < ' a , ' ra , ' tcx > {
@@ -469,6 +586,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
469
586
}
470
587
}
471
588
589
+ #[ instrument( level = "debug" , skip( self ) ) ]
472
590
fn build_reduced_graph_for_use_tree (
473
591
& mut self ,
474
592
// This particular use tree
@@ -482,11 +600,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
482
600
vis : ty:: Visibility ,
483
601
root_span : Span ,
484
602
) {
485
- debug ! (
486
- "build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})" ,
487
- parent_prefix, use_tree, nested
488
- ) ;
489
-
490
603
// Top level use tree reuses the item's id and list stems reuse their parent
491
604
// use tree's ids, so in both cases their visibilities are already filled.
492
605
if nested && !list_stem {
@@ -589,7 +702,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
589
702
let crate_root = self . r . resolve_crate_root ( source. ident ) ;
590
703
let crate_name = match crate_root. kind {
591
704
ModuleKind :: Def ( .., name) => name,
592
- ModuleKind :: Block => unreachable ! ( ) ,
705
+ ModuleKind :: Block | ModuleKind :: NamespaceCrate ( .. ) => unreachable ! ( ) ,
593
706
} ;
594
707
// HACK(eddyb) unclear how good this is, but keeping `$crate`
595
708
// in `source` breaks `tests/ui/imports/import-crate-var.rs`,
@@ -897,6 +1010,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
897
1010
}
898
1011
}
899
1012
1013
+ #[ instrument( level = "debug" , skip( self ) ) ]
900
1014
fn build_reduced_graph_for_extern_crate (
901
1015
& mut self ,
902
1016
orig_name : Option < Symbol > ,
@@ -922,7 +1036,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
922
1036
} ) ;
923
1037
crate_id. map ( |crate_id| {
924
1038
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 )
926
1040
} )
927
1041
}
928
1042
. map ( |module| {
0 commit comments