11//! Describes items defined or visible (ie, imported) in a certain scope.
22//! This is shared between modules and blocks.
33
4+ use std:: collections:: hash_map:: Entry ;
5+
46use hir_expand:: name:: Name ;
57use once_cell:: sync:: Lazy ;
68use ra_db:: CrateId ;
@@ -27,7 +29,11 @@ pub struct PerNsGlobImports {
2729
2830#[ derive( Debug , Default , PartialEq , Eq ) ]
2931pub struct ItemScope {
30- visible : FxHashMap < Name , PerNs > ,
32+ types : FxHashMap < Name , ( ModuleDefId , Visibility ) > ,
33+ values : FxHashMap < Name , ( ModuleDefId , Visibility ) > ,
34+ macros : FxHashMap < Name , ( MacroDefId , Visibility ) > ,
35+ unresolved : FxHashSet < Name > ,
36+
3137 defs : Vec < ModuleDefId > ,
3238 impls : Vec < ImplId > ,
3339 /// Macros visible in current module in legacy textual scope
@@ -65,14 +71,16 @@ pub(crate) enum BuiltinShadowMode {
6571/// Other methods will only resolve values, types and module scoped macros only.
6672impl ItemScope {
6773 pub fn entries < ' a > ( & ' a self ) -> impl Iterator < Item = ( & ' a Name , PerNs ) > + ' a {
68- //FIXME: shadowing
69- self . visible . iter ( ) . map ( |( n, def) | ( n, * def) )
70- }
71-
72- pub fn entries_without_primitives < ' a > (
73- & ' a self ,
74- ) -> impl Iterator < Item = ( & ' a Name , PerNs ) > + ' a {
75- self . visible . iter ( ) . map ( |( n, def) | ( n, * def) )
74+ // FIXME: shadowing
75+ let keys: FxHashSet < _ > = self
76+ . types
77+ . keys ( )
78+ . chain ( self . values . keys ( ) )
79+ . chain ( self . macros . keys ( ) )
80+ . chain ( self . unresolved . iter ( ) )
81+ . collect ( ) ;
82+
83+ keys. into_iter ( ) . map ( move |name| ( name, self . get ( name) ) )
7684 }
7785
7886 pub fn declarations ( & self ) -> impl Iterator < Item = ModuleDefId > + ' _ {
@@ -91,7 +99,7 @@ impl ItemScope {
9199
92100 /// Iterate over all module scoped macros
93101 pub ( crate ) fn macros < ' a > ( & ' a self ) -> impl Iterator < Item = ( & ' a Name , MacroDefId ) > + ' a {
94- self . visible . iter ( ) . filter_map ( |( name, def) | def. take_macros ( ) . map ( |macro_| ( name, macro_) ) )
102+ self . entries ( ) . filter_map ( |( name, def) | def. take_macros ( ) . map ( |macro_| ( name, macro_) ) )
95103 }
96104
97105 /// Iterate over all legacy textual scoped macros visible at the end of the module
@@ -101,21 +109,25 @@ impl ItemScope {
101109
102110 /// Get a name from current module scope, legacy macros are not included
103111 pub ( crate ) fn get ( & self , name : & Name ) -> PerNs {
104- self . visible . get ( name) . copied ( ) . unwrap_or_else ( PerNs :: none)
112+ PerNs {
113+ types : self . types . get ( name) . copied ( ) ,
114+ values : self . values . get ( name) . copied ( ) ,
115+ macros : self . macros . get ( name) . copied ( ) ,
116+ }
105117 }
106118
107119 pub ( crate ) fn name_of ( & self , item : ItemInNs ) -> Option < ( & Name , Visibility ) > {
108- for ( name, per_ns) in & self . visible {
109- if let Some ( vis) = item. match_with ( * per_ns) {
120+ for ( name, per_ns) in self . entries ( ) {
121+ if let Some ( vis) = item. match_with ( per_ns) {
110122 return Some ( ( name, vis) ) ;
111123 }
112124 }
113125 None
114126 }
115127
116128 pub ( crate ) fn traits < ' a > ( & ' a self ) -> impl Iterator < Item = TraitId > + ' a {
117- self . visible . values ( ) . filter_map ( |def| match def. take_types ( ) {
118- Some ( ModuleDefId :: TraitId ( t) ) => Some ( t) ,
129+ self . types . values ( ) . filter_map ( |( def, _ ) | match def {
130+ ModuleDefId :: TraitId ( t) => Some ( * t) ,
119131 _ => None ,
120132 } )
121133 }
@@ -138,21 +150,30 @@ impl ItemScope {
138150
139151 pub ( crate ) fn push_res ( & mut self , name : Name , def : PerNs ) -> bool {
140152 let mut changed = false ;
141- let existing = self . visible . entry ( name) . or_default ( ) ;
142153
143- if existing. types . is_none ( ) && def. types . is_some ( ) {
144- existing. types = def. types ;
145- changed = true ;
154+ if let Some ( types) = def. types {
155+ self . types . entry ( name. clone ( ) ) . or_insert_with ( || {
156+ changed = true ;
157+ types
158+ } ) ;
146159 }
147-
148- if existing. values . is_none ( ) && def. values . is_some ( ) {
149- existing. values = def. values ;
150- changed = true ;
160+ if let Some ( values) = def. values {
161+ self . values . entry ( name. clone ( ) ) . or_insert_with ( || {
162+ changed = true ;
163+ values
164+ } ) ;
165+ }
166+ if let Some ( macros) = def. macros {
167+ self . macros . entry ( name. clone ( ) ) . or_insert_with ( || {
168+ changed = true ;
169+ macros
170+ } ) ;
151171 }
152172
153- if existing. macros . is_none ( ) && def. macros . is_some ( ) {
154- existing. macros = def. macros ;
155- changed = true ;
173+ if def. is_none ( ) {
174+ if self . unresolved . insert ( name) {
175+ changed = true ;
176+ }
156177 }
157178
158179 changed
@@ -166,17 +187,17 @@ impl ItemScope {
166187 def_import_type : ImportType ,
167188 ) -> bool {
168189 let mut changed = false ;
169- let existing = self . visible . entry ( lookup. 1 . clone ( ) ) . or_default ( ) ;
170190
171191 macro_rules! check_changed {
172192 (
173193 $changed: ident,
174- ( $existing : ident / $def: ident ) . $field: ident,
194+ ( $this : ident / $def: ident ) . $field: ident,
175195 $glob_imports: ident [ $lookup: ident ] ,
176196 $def_import_type: ident
177- ) => {
178- match ( $existing. $field, $def. $field) {
179- ( None , Some ( _) ) => {
197+ ) => { {
198+ let existing = $this. $field. entry( $lookup. 1 . clone( ) ) ;
199+ match ( existing, $def. $field) {
200+ ( Entry :: Vacant ( entry) , Some ( _) ) => {
180201 match $def_import_type {
181202 ImportType :: Glob => {
182203 $glob_imports. $field. insert( $lookup. clone( ) ) ;
@@ -186,32 +207,42 @@ impl ItemScope {
186207 }
187208 }
188209
189- $existing. $field = $def. $field;
210+ if let Some ( fld) = $def. $field {
211+ entry. insert( fld) ;
212+ }
190213 $changed = true ;
191214 }
192- ( Some ( _ ) , Some ( _) )
215+ ( Entry :: Occupied ( mut entry ) , Some ( _) )
193216 if $glob_imports. $field. contains( & $lookup)
194217 && matches!( $def_import_type, ImportType :: Named ) =>
195218 {
196219 mark:: hit!( import_shadowed) ;
197220 $glob_imports. $field. remove( & $lookup) ;
198- $existing. $field = $def. $field;
221+ if let Some ( fld) = $def. $field {
222+ entry. insert( fld) ;
223+ }
199224 $changed = true ;
200225 }
201226 _ => { }
202227 }
203- } ;
228+ } } ;
204229 }
205230
206- check_changed ! ( changed, ( existing / def) . types, glob_imports[ lookup] , def_import_type) ;
207- check_changed ! ( changed, ( existing / def) . values, glob_imports[ lookup] , def_import_type) ;
208- check_changed ! ( changed, ( existing / def) . macros, glob_imports[ lookup] , def_import_type) ;
231+ check_changed ! ( changed, ( self / def) . types, glob_imports[ lookup] , def_import_type) ;
232+ check_changed ! ( changed, ( self / def) . values, glob_imports[ lookup] , def_import_type) ;
233+ check_changed ! ( changed, ( self / def) . macros, glob_imports[ lookup] , def_import_type) ;
234+
235+ if def. is_none ( ) {
236+ if self . unresolved . insert ( lookup. 1 ) {
237+ changed = true ;
238+ }
239+ }
209240
210241 changed
211242 }
212243
213244 pub ( crate ) fn resolutions < ' a > ( & ' a self ) -> impl Iterator < Item = ( Name , PerNs ) > + ' a {
214- self . visible . iter ( ) . map ( |( name, res) | ( name. clone ( ) , * res) )
245+ self . entries ( ) . map ( |( name, res) | ( name. clone ( ) , res) )
215246 }
216247
217248 pub ( crate ) fn collect_legacy_macros ( & self ) -> FxHashMap < Name , MacroDefId > {
0 commit comments