@@ -18,9 +18,11 @@ pub(crate) mod lower;
18
18
19
19
use std:: { time, sync:: Arc } ;
20
20
21
+ use rustc_hash:: { FxHashMap , FxHashSet } ;
22
+
21
23
use ra_arena:: map:: ArenaMap ;
24
+ use ra_db:: Edition ;
22
25
use test_utils:: tested_by;
23
- use rustc_hash:: { FxHashMap , FxHashSet } ;
24
26
25
27
use crate :: {
26
28
Module , ModuleDef ,
@@ -32,8 +34,9 @@ use crate::{
32
34
33
35
/// `ItemMap` is the result of module name resolution. It contains, for each
34
36
/// module, the set of visible items.
35
- #[ derive( Default , Debug , PartialEq , Eq ) ]
37
+ #[ derive( Debug , PartialEq , Eq ) ]
36
38
pub struct ItemMap {
39
+ edition : Edition ,
37
40
/// The prelude module for this crate. This either comes from an import
38
41
/// marked with the `prelude_import` attribute, or (in the normal case) from
39
42
/// a dependency (`std` or `core`).
@@ -180,7 +183,12 @@ where
180
183
module_tree,
181
184
processed_imports : FxHashSet :: default ( ) ,
182
185
glob_imports : FxHashMap :: default ( ) ,
183
- result : ItemMap :: default ( ) ,
186
+ result : ItemMap {
187
+ edition : krate. edition ( db) ,
188
+ prelude : None ,
189
+ extern_prelude : FxHashMap :: default ( ) ,
190
+ per_module : ArenaMap :: default ( ) ,
191
+ } ,
184
192
}
185
193
}
186
194
@@ -277,10 +285,14 @@ where
277
285
import_id : ImportId ,
278
286
import : & ImportData ,
279
287
) -> ReachedFixedPoint {
280
- log:: debug!( "resolving import: {:?}" , import) ;
288
+ log:: debug!( "resolving import: {:?} ({:?}) " , import, self . result . edition ) ;
281
289
let original_module = Module { krate : self . krate , module_id } ;
282
- let ( def, reached_fixedpoint) =
283
- self . result . resolve_path_fp ( self . db , original_module, & import. path ) ;
290
+ let ( def, reached_fixedpoint) = self . result . resolve_path_fp (
291
+ self . db ,
292
+ ResolveMode :: Import ,
293
+ original_module,
294
+ & import. path ,
295
+ ) ;
284
296
285
297
if reached_fixedpoint != ReachedFixedPoint :: Yes {
286
298
return reached_fixedpoint;
@@ -417,6 +429,12 @@ where
417
429
}
418
430
}
419
431
432
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
433
+ enum ResolveMode {
434
+ Import ,
435
+ Other ,
436
+ }
437
+
420
438
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
421
439
enum ReachedFixedPoint {
422
440
Yes ,
@@ -445,7 +463,7 @@ impl ItemMap {
445
463
original_module : Module ,
446
464
path : & Path ,
447
465
) -> PerNs < ModuleDef > {
448
- self . resolve_path_fp ( db, original_module, path) . 0
466
+ self . resolve_path_fp ( db, ResolveMode :: Other , original_module, path) . 0
449
467
}
450
468
451
469
fn resolve_in_prelude (
@@ -484,23 +502,54 @@ impl ItemMap {
484
502
from_scope. or ( from_extern_prelude) . or ( from_prelude)
485
503
}
486
504
505
+ fn resolve_name_in_crate_root_or_extern_prelude (
506
+ & self ,
507
+ db : & impl PersistentHirDatabase ,
508
+ module : Module ,
509
+ name : & Name ,
510
+ ) -> PerNs < ModuleDef > {
511
+ let crate_root = module. crate_root ( db) ;
512
+ let from_crate_root = self [ crate_root. module_id ] . items . get ( name) . map_or ( PerNs :: none ( ) , |it| it. def ) ;
513
+ let from_extern_prelude =
514
+ self . extern_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& it| PerNs :: types ( it) ) ;
515
+
516
+ from_crate_root. or ( from_extern_prelude)
517
+ }
518
+
487
519
// Returns Yes if we are sure that additions to `ItemMap` wouldn't change
488
520
// the result.
489
521
fn resolve_path_fp (
490
522
& self ,
491
523
db : & impl PersistentHirDatabase ,
524
+ mode : ResolveMode ,
492
525
original_module : Module ,
493
526
path : & Path ,
494
527
) -> ( PerNs < ModuleDef > , ReachedFixedPoint ) {
495
528
let mut segments = path. segments . iter ( ) . enumerate ( ) ;
496
529
let mut curr_per_ns: PerNs < ModuleDef > = match path. kind {
497
530
PathKind :: Crate => PerNs :: types ( original_module. crate_root ( db) . into ( ) ) ,
498
531
PathKind :: Self_ => PerNs :: types ( original_module. into ( ) ) ,
532
+ // plain import or absolute path in 2015: crate-relative with
533
+ // fallback to extern prelude (with the simplification in
534
+ // rust-lang/rust#57745)
535
+ // TODO there must be a nicer way to write this condition
536
+ PathKind :: Plain | PathKind :: Abs
537
+ if self . edition == Edition :: Edition2015
538
+ && ( path. kind == PathKind :: Abs || mode == ResolveMode :: Import ) =>
539
+ {
540
+ let segment = match segments. next ( ) {
541
+ Some ( ( _, segment) ) => segment,
542
+ None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
543
+ } ;
544
+ log:: debug!( "resolving {:?} in crate root (+ extern prelude)" , segment) ;
545
+ self . resolve_name_in_crate_root_or_extern_prelude ( db, original_module, & segment. name )
546
+ }
499
547
PathKind :: Plain => {
500
548
let segment = match segments. next ( ) {
501
549
Some ( ( _, segment) ) => segment,
502
550
None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
503
551
} ;
552
+ log:: debug!( "resolving {:?} in module" , segment) ;
504
553
self . resolve_name_in_module ( db, original_module, & segment. name )
505
554
}
506
555
PathKind :: Super => {
0 commit comments