1010//!
1111//! `ReachedFixedPoint` signals about this.
1212
13+ use either:: Either ;
1314use hir_expand:: { name:: Name , Lookup } ;
1415use span:: Edition ;
1516use triomphe:: Arc ;
@@ -150,17 +151,8 @@ impl DefMap {
150151
151152 let mut arc;
152153 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- ) ;
162154
163- // Merge ` new` into `result`.
155+ let mut merge = | new : ResolvePathResult | {
164156 result. resolved_def = result. resolved_def . or ( new. resolved_def ) ;
165157 if result. reached_fixedpoint == ReachedFixedPoint :: No {
166158 result. reached_fixedpoint = new. reached_fixedpoint ;
@@ -171,7 +163,9 @@ impl DefMap {
171163 ( Some ( old) , Some ( new) ) => Some ( old. max ( new) ) ,
172164 ( None , new) => new,
173165 } ;
166+ } ;
174167
168+ loop {
175169 match current_map. block {
176170 Some ( block) if original_module == Self :: ROOT => {
177171 // Block modules "inherit" names from its parent module.
@@ -180,8 +174,38 @@ impl DefMap {
180174 current_map = & arc;
181175 }
182176 // 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+ }
184197 }
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) ;
185209 }
186210 }
187211
@@ -195,7 +219,7 @@ impl DefMap {
195219 expected_macro_subns : Option < MacroSubNs > ,
196220 ) -> ResolvePathResult {
197221 let mut segments = path. segments ( ) . iter ( ) . enumerate ( ) ;
198- let mut curr_per_ns = match path. kind {
222+ let curr_per_ns = match path. kind {
199223 PathKind :: DollarCrate ( krate) => {
200224 if krate == self . krate {
201225 cov_mark:: hit!( macro_dollar_crate_self) ;
@@ -296,25 +320,96 @@ impl DefMap {
296320
297321 PerNs :: types ( module. into ( ) , Visibility :: Public , None )
298322 }
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) ,
303355 None => return ResolvePathResult :: empty ( ReachedFixedPoint :: Yes ) ,
304356 } ;
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)
314372 }
373+ } ,
374+ PathKind :: DollarCrate ( _) | PathKind :: Crate | PathKind :: Super ( _) => {
375+ return ResolvePathResult :: empty ( ReachedFixedPoint :: Yes )
315376 }
316377 } ;
317378
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 {
318413 for ( i, segment) in segments {
319414 let ( curr, vis, imp) = match curr_per_ns. take_types_full ( ) {
320415 Some ( r) => r,
@@ -475,24 +570,9 @@ impl DefMap {
475570 // they might been shadowed by local names.
476571 return PerNs :: none ( ) ;
477572 }
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)
495574 } ;
575+ let macro_use_prelude = || self . resolve_in_macro_use_prelude ( name) ;
496576 let prelude = || {
497577 if self . block . is_some ( ) && module == DefMap :: ROOT {
498578 return PerNs :: none ( ) ;
@@ -507,6 +587,38 @@ impl DefMap {
507587 . or_else ( prelude)
508588 }
509589
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+
510622 fn resolve_name_in_crate_root_or_extern_prelude (
511623 & self ,
512624 db : & dyn DefDatabase ,
@@ -525,16 +637,7 @@ impl DefMap {
525637 // Don't resolve extern prelude in pseudo-module of a block.
526638 return PerNs :: none ( ) ;
527639 }
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)
538641 } ;
539642
540643 from_crate_root. or_else ( from_extern_prelude)
0 commit comments