@@ -18,9 +18,11 @@ pub(crate) mod lower;
1818
1919use std:: { time, sync:: Arc } ;
2020
21+ use rustc_hash:: { FxHashMap , FxHashSet } ;
22+
2123use ra_arena:: map:: ArenaMap ;
24+ use ra_db:: Edition ;
2225use test_utils:: tested_by;
23- use rustc_hash:: { FxHashMap , FxHashSet } ;
2426
2527use crate :: {
2628 Module , ModuleDef ,
@@ -32,8 +34,9 @@ use crate::{
3234
3335/// `ItemMap` is the result of module name resolution. It contains, for each
3436/// module, the set of visible items.
35- #[ derive( Default , Debug , PartialEq , Eq ) ]
37+ #[ derive( Debug , PartialEq , Eq ) ]
3638pub struct ItemMap {
39+ edition : Edition ,
3740 /// The prelude module for this crate. This either comes from an import
3841 /// marked with the `prelude_import` attribute, or (in the normal case) from
3942 /// a dependency (`std` or `core`).
@@ -180,7 +183,12 @@ where
180183 module_tree,
181184 processed_imports : FxHashSet :: default ( ) ,
182185 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+ } ,
184192 }
185193 }
186194
@@ -277,10 +285,14 @@ where
277285 import_id : ImportId ,
278286 import : & ImportData ,
279287 ) -> ReachedFixedPoint {
280- log:: debug!( "resolving import: {:?}" , import) ;
288+ log:: debug!( "resolving import: {:?} ({:?}) " , import, self . result . edition ) ;
281289 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+ ) ;
284296
285297 if reached_fixedpoint != ReachedFixedPoint :: Yes {
286298 return reached_fixedpoint;
@@ -417,6 +429,12 @@ where
417429 }
418430}
419431
432+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
433+ enum ResolveMode {
434+ Import ,
435+ Other ,
436+ }
437+
420438#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
421439enum ReachedFixedPoint {
422440 Yes ,
@@ -445,7 +463,7 @@ impl ItemMap {
445463 original_module : Module ,
446464 path : & Path ,
447465 ) -> PerNs < ModuleDef > {
448- self . resolve_path_fp ( db, original_module, path) . 0
466+ self . resolve_path_fp ( db, ResolveMode :: Other , original_module, path) . 0
449467 }
450468
451469 fn resolve_in_prelude (
@@ -484,23 +502,54 @@ impl ItemMap {
484502 from_scope. or ( from_extern_prelude) . or ( from_prelude)
485503 }
486504
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+
487519 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
488520 // the result.
489521 fn resolve_path_fp (
490522 & self ,
491523 db : & impl PersistentHirDatabase ,
524+ mode : ResolveMode ,
492525 original_module : Module ,
493526 path : & Path ,
494527 ) -> ( PerNs < ModuleDef > , ReachedFixedPoint ) {
495528 let mut segments = path. segments . iter ( ) . enumerate ( ) ;
496529 let mut curr_per_ns: PerNs < ModuleDef > = match path. kind {
497530 PathKind :: Crate => PerNs :: types ( original_module. crate_root ( db) . into ( ) ) ,
498531 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+ }
499547 PathKind :: Plain => {
500548 let segment = match segments. next ( ) {
501549 Some ( ( _, segment) ) => segment,
502550 None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
503551 } ;
552+ log:: debug!( "resolving {:?} in module" , segment) ;
504553 self . resolve_name_in_module ( db, original_module, & segment. name )
505554 }
506555 PathKind :: Super => {
0 commit comments