10
10
//!
11
11
//! `ReachedFixedPoint` signals about this.
12
12
13
+ use either:: Either ;
13
14
use hir_expand:: { name:: Name , Lookup } ;
14
15
use span:: Edition ;
15
16
use triomphe:: Arc ;
@@ -150,17 +151,8 @@ impl DefMap {
150
151
151
152
let mut arc;
152
153
let mut current_map = self ;
153
- loop {
154
- let new = current_map. resolve_path_fp_with_macro_single (
155
- db,
156
- mode,
157
- original_module,
158
- path,
159
- shadow,
160
- expected_macro_subns,
161
- ) ;
162
154
163
- // Merge ` new` into `result`.
155
+ let mut merge = | new : ResolvePathResult | {
164
156
result. resolved_def = result. resolved_def . or ( new. resolved_def ) ;
165
157
if result. reached_fixedpoint == ReachedFixedPoint :: No {
166
158
result. reached_fixedpoint = new. reached_fixedpoint ;
@@ -171,7 +163,9 @@ impl DefMap {
171
163
( Some ( old) , Some ( new) ) => Some ( old. max ( new) ) ,
172
164
( None , new) => new,
173
165
} ;
166
+ } ;
174
167
168
+ loop {
175
169
match current_map. block {
176
170
Some ( block) if original_module == Self :: ROOT => {
177
171
// Block modules "inherit" names from its parent module.
@@ -180,8 +174,38 @@ impl DefMap {
180
174
current_map = & arc;
181
175
}
182
176
// Proper (non-block) modules, including those in block `DefMap`s, don't.
183
- _ => return result,
177
+ _ => {
178
+ if original_module != Self :: ROOT && current_map. block . is_some ( ) {
179
+ // A module inside a block. Do not resolve items declared in upper blocks, but we do need to get
180
+ // the prelude items (which are not inserted into blocks because they can be overridden there).
181
+ original_module = Self :: ROOT ;
182
+ arc = db. crate_def_map ( self . krate ) ;
183
+ current_map = & arc;
184
+
185
+ let new = current_map. resolve_path_fp_in_all_preludes (
186
+ db,
187
+ mode,
188
+ original_module,
189
+ path,
190
+ shadow,
191
+ ) ;
192
+ merge ( new) ;
193
+ }
194
+
195
+ return result;
196
+ }
184
197
}
198
+
199
+ let new = current_map. resolve_path_fp_with_macro_single (
200
+ db,
201
+ mode,
202
+ original_module,
203
+ path,
204
+ shadow,
205
+ expected_macro_subns,
206
+ ) ;
207
+
208
+ merge ( new) ;
185
209
}
186
210
}
187
211
@@ -195,7 +219,7 @@ impl DefMap {
195
219
expected_macro_subns : Option < MacroSubNs > ,
196
220
) -> ResolvePathResult {
197
221
let mut segments = path. segments ( ) . iter ( ) . enumerate ( ) ;
198
- let mut curr_per_ns = match path. kind {
222
+ let curr_per_ns = match path. kind {
199
223
PathKind :: DollarCrate ( krate) => {
200
224
if krate == self . krate {
201
225
cov_mark:: hit!( macro_dollar_crate_self) ;
@@ -296,25 +320,96 @@ impl DefMap {
296
320
297
321
PerNs :: types ( module. into ( ) , Visibility :: Public , None )
298
322
}
299
- PathKind :: Abs => {
300
- // 2018-style absolute path -- only extern prelude
301
- let segment = match segments. next ( ) {
302
- Some ( ( _, segment) ) => segment,
323
+ PathKind :: Abs => match self . resolve_path_abs ( & mut segments, path) {
324
+ Either :: Left ( it) => it,
325
+ Either :: Right ( reached_fixed_point) => {
326
+ return ResolvePathResult :: empty ( reached_fixed_point)
327
+ }
328
+ } ,
329
+ } ;
330
+
331
+ self . resolve_remaining_segments ( segments, curr_per_ns, path, db, shadow, original_module)
332
+ }
333
+
334
+ /// Resolves a path only in the preludes, without accounting for item scopes.
335
+ pub ( super ) fn resolve_path_fp_in_all_preludes (
336
+ & self ,
337
+ db : & dyn DefDatabase ,
338
+ mode : ResolveMode ,
339
+ original_module : LocalModuleId ,
340
+ path : & ModPath ,
341
+ shadow : BuiltinShadowMode ,
342
+ ) -> ResolvePathResult {
343
+ let mut segments = path. segments ( ) . iter ( ) . enumerate ( ) ;
344
+ let curr_per_ns = match path. kind {
345
+ // plain import or absolute path in 2015: crate-relative with
346
+ // fallback to extern prelude (with the simplification in
347
+ // rust-lang/rust#57745)
348
+ // FIXME there must be a nicer way to write this condition
349
+ PathKind :: Plain | PathKind :: Abs
350
+ if self . data . edition == Edition :: Edition2015
351
+ && ( path. kind == PathKind :: Abs || mode == ResolveMode :: Import ) =>
352
+ {
353
+ let ( _, segment) = match segments. next ( ) {
354
+ Some ( ( idx, segment) ) => ( idx, segment) ,
303
355
None => return ResolvePathResult :: empty ( ReachedFixedPoint :: Yes ) ,
304
356
} ;
305
- if let Some ( & ( def, extern_crate) ) = self . data . extern_prelude . get ( segment) {
306
- tracing:: debug!( "absolute path {:?} resolved to crate {:?}" , path, def) ;
307
- PerNs :: types (
308
- def. into ( ) ,
309
- Visibility :: Public ,
310
- extern_crate. map ( ImportOrExternCrate :: ExternCrate ) ,
311
- )
312
- } else {
313
- return ResolvePathResult :: empty ( ReachedFixedPoint :: No ) ; // extern crate declarations can add to the extern prelude
357
+ tracing:: debug!( "resolving {:?} in crate root (+ extern prelude)" , segment) ;
358
+ self . resolve_name_in_extern_prelude ( segment)
359
+ }
360
+ PathKind :: Plain => {
361
+ let ( _, segment) = match segments. next ( ) {
362
+ Some ( ( idx, segment) ) => ( idx, segment) ,
363
+ None => return ResolvePathResult :: empty ( ReachedFixedPoint :: Yes ) ,
364
+ } ;
365
+ tracing:: debug!( "resolving {:?} in module" , segment) ;
366
+ self . resolve_name_in_all_preludes ( db, segment)
367
+ }
368
+ PathKind :: Abs => match self . resolve_path_abs ( & mut segments, path) {
369
+ Either :: Left ( it) => it,
370
+ Either :: Right ( reached_fixed_point) => {
371
+ return ResolvePathResult :: empty ( reached_fixed_point)
314
372
}
373
+ } ,
374
+ PathKind :: DollarCrate ( _) | PathKind :: Crate | PathKind :: Super ( _) => {
375
+ return ResolvePathResult :: empty ( ReachedFixedPoint :: Yes )
315
376
}
316
377
} ;
317
378
379
+ self . resolve_remaining_segments ( segments, curr_per_ns, path, db, shadow, original_module)
380
+ }
381
+
382
+ /// 2018-style absolute path -- only extern prelude
383
+ fn resolve_path_abs < ' a > (
384
+ & self ,
385
+ segments : & mut impl Iterator < Item = ( usize , & ' a Name ) > ,
386
+ path : & ModPath ,
387
+ ) -> Either < PerNs , ReachedFixedPoint > {
388
+ let segment = match segments. next ( ) {
389
+ Some ( ( _, segment) ) => segment,
390
+ None => return Either :: Right ( ReachedFixedPoint :: Yes ) ,
391
+ } ;
392
+ if let Some ( & ( def, extern_crate) ) = self . data . extern_prelude . get ( segment) {
393
+ tracing:: debug!( "absolute path {:?} resolved to crate {:?}" , path, def) ;
394
+ Either :: Left ( PerNs :: types (
395
+ def. into ( ) ,
396
+ Visibility :: Public ,
397
+ extern_crate. map ( ImportOrExternCrate :: ExternCrate ) ,
398
+ ) )
399
+ } else {
400
+ Either :: Right ( ReachedFixedPoint :: No ) // extern crate declarations can add to the extern prelude
401
+ }
402
+ }
403
+
404
+ fn resolve_remaining_segments < ' a > (
405
+ & self ,
406
+ segments : impl Iterator < Item = ( usize , & ' a Name ) > ,
407
+ mut curr_per_ns : PerNs ,
408
+ path : & ModPath ,
409
+ db : & dyn DefDatabase ,
410
+ shadow : BuiltinShadowMode ,
411
+ original_module : LocalModuleId ,
412
+ ) -> ResolvePathResult {
318
413
for ( i, segment) in segments {
319
414
let ( curr, vis, imp) = match curr_per_ns. take_types_full ( ) {
320
415
Some ( r) => r,
@@ -475,24 +570,9 @@ impl DefMap {
475
570
// they might been shadowed by local names.
476
571
return PerNs :: none ( ) ;
477
572
}
478
- self . data . extern_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& ( it, extern_crate) | {
479
- PerNs :: types (
480
- it. into ( ) ,
481
- Visibility :: Public ,
482
- extern_crate. map ( ImportOrExternCrate :: ExternCrate ) ,
483
- )
484
- } )
485
- } ;
486
- let macro_use_prelude = || {
487
- self . macro_use_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& ( it, _extern_crate) | {
488
- PerNs :: macros (
489
- it,
490
- Visibility :: Public ,
491
- // FIXME?
492
- None , // extern_crate.map(ImportOrExternCrate::ExternCrate),
493
- )
494
- } )
573
+ self . resolve_name_in_extern_prelude ( name)
495
574
} ;
575
+ let macro_use_prelude = || self . resolve_in_macro_use_prelude ( name) ;
496
576
let prelude = || {
497
577
if self . block . is_some ( ) && module == DefMap :: ROOT {
498
578
return PerNs :: none ( ) ;
@@ -507,6 +587,38 @@ impl DefMap {
507
587
. or_else ( prelude)
508
588
}
509
589
590
+ fn resolve_name_in_all_preludes ( & self , db : & dyn DefDatabase , name : & Name ) -> PerNs {
591
+ // Resolve in:
592
+ // - extern prelude / macro_use prelude
593
+ // - std prelude
594
+ let extern_prelude = self . resolve_name_in_extern_prelude ( name) ;
595
+ let macro_use_prelude = || self . resolve_in_macro_use_prelude ( name) ;
596
+ let prelude = || self . resolve_in_prelude ( db, name) ;
597
+
598
+ extern_prelude. or_else ( macro_use_prelude) . or_else ( prelude)
599
+ }
600
+
601
+ fn resolve_name_in_extern_prelude ( & self , name : & Name ) -> PerNs {
602
+ self . data . extern_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& ( it, extern_crate) | {
603
+ PerNs :: types (
604
+ it. into ( ) ,
605
+ Visibility :: Public ,
606
+ extern_crate. map ( ImportOrExternCrate :: ExternCrate ) ,
607
+ )
608
+ } )
609
+ }
610
+
611
+ fn resolve_in_macro_use_prelude ( & self , name : & Name ) -> PerNs {
612
+ self . macro_use_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& ( it, _extern_crate) | {
613
+ PerNs :: macros (
614
+ it,
615
+ Visibility :: Public ,
616
+ // FIXME?
617
+ None , // extern_crate.map(ImportOrExternCrate::ExternCrate),
618
+ )
619
+ } )
620
+ }
621
+
510
622
fn resolve_name_in_crate_root_or_extern_prelude (
511
623
& self ,
512
624
db : & dyn DefDatabase ,
@@ -525,16 +637,7 @@ impl DefMap {
525
637
// Don't resolve extern prelude in pseudo-module of a block.
526
638
return PerNs :: none ( ) ;
527
639
}
528
- self . data . extern_prelude . get ( name) . copied ( ) . map_or (
529
- PerNs :: none ( ) ,
530
- |( it, extern_crate) | {
531
- PerNs :: types (
532
- it. into ( ) ,
533
- Visibility :: Public ,
534
- extern_crate. map ( ImportOrExternCrate :: ExternCrate ) ,
535
- )
536
- } ,
537
- )
640
+ self . resolve_name_in_extern_prelude ( name)
538
641
} ;
539
642
540
643
from_crate_root. or_else ( from_extern_prelude)
0 commit comments