@@ -34,6 +34,10 @@ use crate::{
3434/// module, the set of visible items.
3535#[ derive( Default , Debug , PartialEq , Eq ) ]
3636pub struct ItemMap {
37+ /// The prelude module for this crate. This either comes from an import
38+ /// marked with the `prelude_import` attribute, or (in the normal case) from
39+ /// a dependency (`std` or `core`).
40+ prelude : Option < Module > ,
3741 pub ( crate ) extern_prelude : FxHashMap < Name , ModuleDef > ,
3842 per_module : ArenaMap < ModuleId , ModuleScope > ,
3943}
@@ -211,6 +215,13 @@ where
211215 if let Some ( module) = dep. krate . root_module ( self . db ) {
212216 self . result . extern_prelude . insert ( dep. name . clone ( ) , module. into ( ) ) ;
213217 }
218+ // look for the prelude
219+ if self . result . prelude . is_none ( ) {
220+ let item_map = self . db . item_map ( dep. krate ) ;
221+ if item_map. prelude . is_some ( ) {
222+ self . result . prelude = item_map. prelude ;
223+ }
224+ }
214225 }
215226 }
216227
@@ -279,7 +290,10 @@ where
279290 log:: debug!( "glob import: {:?}" , import) ;
280291 match def. take_types ( ) {
281292 Some ( ModuleDef :: Module ( m) ) => {
282- if m. krate != self . krate {
293+ if import. is_prelude {
294+ tested_by ! ( std_prelude) ;
295+ self . result . prelude = Some ( m) ;
296+ } else if m. krate != self . krate {
283297 tested_by ! ( glob_across_crates) ;
284298 // glob import from other crate => we can just import everything once
285299 let item_map = self . db . item_map ( m. krate ) ;
@@ -434,12 +448,40 @@ impl ItemMap {
434448 self . resolve_path_fp ( db, original_module, path) . 0
435449 }
436450
437- pub ( crate ) fn resolve_name_in_module ( & self , module : Module , name : & Name ) -> PerNs < ModuleDef > {
451+ fn resolve_in_prelude (
452+ & self ,
453+ db : & impl PersistentHirDatabase ,
454+ original_module : Module ,
455+ name : & Name ,
456+ ) -> PerNs < ModuleDef > {
457+ if let Some ( prelude) = self . prelude {
458+ let resolution = if prelude. krate == original_module. krate {
459+ self [ prelude. module_id ] . items . get ( name) . cloned ( )
460+ } else {
461+ db. item_map ( prelude. krate ) [ prelude. module_id ] . items . get ( name) . cloned ( )
462+ } ;
463+ resolution. map ( |r| r. def ) . unwrap_or_else ( PerNs :: none)
464+ } else {
465+ PerNs :: none ( )
466+ }
467+ }
468+
469+ pub ( crate ) fn resolve_name_in_module (
470+ & self ,
471+ db : & impl PersistentHirDatabase ,
472+ module : Module ,
473+ name : & Name ,
474+ ) -> PerNs < ModuleDef > {
475+ // Resolve in:
476+ // - current module / scope
477+ // - extern prelude
478+ // - std prelude
438479 let from_scope = self [ module. module_id ] . items . get ( name) . map_or ( PerNs :: none ( ) , |it| it. def ) ;
439480 let from_extern_prelude =
440481 self . extern_prelude . get ( name) . map_or ( PerNs :: none ( ) , |& it| PerNs :: types ( it) ) ;
482+ let from_prelude = self . resolve_in_prelude ( db, module, name) ;
441483
442- from_scope. or ( from_extern_prelude)
484+ from_scope. or ( from_extern_prelude) . or ( from_prelude )
443485 }
444486
445487 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -459,7 +501,7 @@ impl ItemMap {
459501 Some ( ( _, segment) ) => segment,
460502 None => return ( PerNs :: none ( ) , ReachedFixedPoint :: Yes ) ,
461503 } ;
462- self . resolve_name_in_module ( original_module, & segment. name )
504+ self . resolve_name_in_module ( db , original_module, & segment. name )
463505 }
464506 PathKind :: Super => {
465507 if let Some ( p) = original_module. parent ( db) {
0 commit comments