@@ -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,59 @@ 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 =
513+ self [ crate_root. module_id ] . items . get ( name) . map_or ( PerNs :: none ( ) , |it| it. def ) ;
514+ let from_extern_prelude =
515+ self . extern_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& it| PerNs :: types ( it) ) ;
516+
517+ from_crate_root. or ( from_extern_prelude)
518+ }
519+
487520 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
488521 // the result.
489522 fn resolve_path_fp (
490523 & self ,
491524 db : & impl PersistentHirDatabase ,
525+ mode : ResolveMode ,
492526 original_module : Module ,
493527 path : & Path ,
494528 ) -> ( PerNs < ModuleDef > , ReachedFixedPoint ) {
495529 let mut segments = path. segments . iter ( ) . enumerate ( ) ;
496530 let mut curr_per_ns: PerNs < ModuleDef > = match path. kind {
497531 PathKind :: Crate => PerNs :: types ( original_module. crate_root ( db) . into ( ) ) ,
498532 PathKind :: Self_ => PerNs :: types ( original_module. into ( ) ) ,
533+ // plain import or absolute path in 2015: crate-relative with
534+ // fallback to extern prelude (with the simplification in
535+ // rust-lang/rust#57745)
536+ // TODO there must be a nicer way to write this condition
537+ PathKind :: Plain | PathKind :: Abs
538+ if self . edition == Edition :: Edition2015
539+ && ( path. kind == PathKind :: Abs || mode == ResolveMode :: Import ) =>
540+ {
541+ let segment = match segments. next ( ) {
542+ Some ( ( _, segment) ) => segment,
543+ None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
544+ } ;
545+ log:: debug!( "resolving {:?} in crate root (+ extern prelude)" , segment) ;
546+ self . resolve_name_in_crate_root_or_extern_prelude (
547+ db,
548+ original_module,
549+ & segment. name ,
550+ )
551+ }
499552 PathKind :: Plain => {
500553 let segment = match segments. next ( ) {
501554 Some ( ( _, segment) ) => segment,
502555 None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
503556 } ;
557+ log:: debug!( "resolving {:?} in module" , segment) ;
504558 self . resolve_name_in_module ( db, original_module, & segment. name )
505559 }
506560 PathKind :: Super => {
0 commit comments