@@ -11,6 +11,7 @@ use crate::{
1111 db:: DefDatabase , per_ns:: PerNs , visibility:: Visibility , AdtId , BuiltinType , HasModule , ImplId ,
1212 LocalModuleId , Lookup , MacroDefId , ModuleDefId , TraitId ,
1313} ;
14+ use std:: collections:: hash_map:: Entry ;
1415
1516#[ derive( Copy , Clone ) ]
1617pub ( crate ) enum ImportType {
@@ -27,7 +28,11 @@ pub struct PerNsGlobImports {
2728
2829#[ derive( Debug , Default , PartialEq , Eq ) ]
2930pub struct ItemScope {
30- visible : FxHashMap < Name , PerNs > ,
31+ types : FxHashMap < Name , ( ModuleDefId , Visibility ) > ,
32+ values : FxHashMap < Name , ( ModuleDefId , Visibility ) > ,
33+ macros : FxHashMap < Name , ( MacroDefId , Visibility ) > ,
34+ unresolved : FxHashSet < Name > ,
35+
3136 defs : Vec < ModuleDefId > ,
3237 impls : Vec < ImplId > ,
3338 /// Macros visible in current module in legacy textual scope
@@ -65,14 +70,22 @@ pub(crate) enum BuiltinShadowMode {
6570/// Other methods will only resolve values, types and module scoped macros only.
6671impl ItemScope {
6772 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) )
73+ // FIXME: shadowing
74+ let keys: FxHashSet < _ > = self
75+ . types
76+ . keys ( )
77+ . chain ( self . values . keys ( ) )
78+ . chain ( self . macros . keys ( ) )
79+ . chain ( self . unresolved . iter ( ) )
80+ . collect ( ) ;
81+
82+ keys. into_iter ( ) . map ( move |name| ( name, self . get ( name) ) )
7083 }
7184
7285 pub fn entries_without_primitives < ' a > (
7386 & ' a self ,
7487 ) -> impl Iterator < Item = ( & ' a Name , PerNs ) > + ' a {
75- self . visible . iter ( ) . map ( | ( n , def ) | ( n , * def ) )
88+ self . entries ( )
7689 }
7790
7891 pub fn declarations ( & self ) -> impl Iterator < Item = ModuleDefId > + ' _ {
@@ -91,7 +104,7 @@ impl ItemScope {
91104
92105 /// Iterate over all module scoped macros
93106 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_) ) )
107+ self . entries ( ) . filter_map ( |( name, def) | def. take_macros ( ) . map ( |macro_| ( name, macro_) ) )
95108 }
96109
97110 /// Iterate over all legacy textual scoped macros visible at the end of the module
@@ -101,21 +114,25 @@ impl ItemScope {
101114
102115 /// Get a name from current module scope, legacy macros are not included
103116 pub ( crate ) fn get ( & self , name : & Name ) -> PerNs {
104- self . visible . get ( name) . copied ( ) . unwrap_or_else ( PerNs :: none)
117+ PerNs {
118+ types : self . types . get ( name) . copied ( ) ,
119+ values : self . values . get ( name) . copied ( ) ,
120+ macros : self . macros . get ( name) . copied ( ) ,
121+ }
105122 }
106123
107124 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) {
125+ for ( name, per_ns) in self . entries ( ) {
126+ if let Some ( vis) = item. match_with ( per_ns) {
110127 return Some ( ( name, vis) ) ;
111128 }
112129 }
113130 None
114131 }
115132
116133 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) ,
134+ self . types . values ( ) . filter_map ( |( def, _ ) | match def {
135+ ModuleDefId :: TraitId ( t) => Some ( * t) ,
119136 _ => None ,
120137 } )
121138 }
@@ -138,21 +155,39 @@ impl ItemScope {
138155
139156 pub ( crate ) fn push_res ( & mut self , name : Name , def : PerNs ) -> bool {
140157 let mut changed = false ;
141- let existing = self . visible . entry ( name) . or_default ( ) ;
142158
143- if existing. types . is_none ( ) && def. types . is_some ( ) {
144- existing. types = def. types ;
145- changed = true ;
159+ if let Some ( types) = def. types {
160+ match self . types . entry ( name. clone ( ) ) {
161+ Entry :: Occupied ( _) => { }
162+ Entry :: Vacant ( e) => {
163+ e. insert ( types) ;
164+ changed = true ;
165+ }
166+ }
146167 }
147-
148- if existing. values . is_none ( ) && def. values . is_some ( ) {
149- existing. values = def. values ;
150- changed = true ;
168+ if let Some ( values) = def. values {
169+ match self . values . entry ( name. clone ( ) ) {
170+ Entry :: Occupied ( _) => { }
171+ Entry :: Vacant ( e) => {
172+ e. insert ( values) ;
173+ changed = true ;
174+ }
175+ }
176+ }
177+ if let Some ( macros) = def. macros {
178+ match self . macros . entry ( name. clone ( ) ) {
179+ Entry :: Occupied ( _) => { }
180+ Entry :: Vacant ( e) => {
181+ e. insert ( macros) ;
182+ changed = true ;
183+ }
184+ }
151185 }
152186
153- if existing. macros . is_none ( ) && def. macros . is_some ( ) {
154- existing. macros = def. macros ;
155- changed = true ;
187+ if def. is_none ( ) {
188+ if self . unresolved . insert ( name) {
189+ changed = true ;
190+ }
156191 }
157192
158193 changed
@@ -166,17 +201,17 @@ impl ItemScope {
166201 def_import_type : ImportType ,
167202 ) -> bool {
168203 let mut changed = false ;
169- let existing = self . visible . entry ( lookup. 1 . clone ( ) ) . or_default ( ) ;
170204
171205 macro_rules! check_changed {
172206 (
173207 $changed: ident,
174- ( $existing : ident / $def: ident ) . $field: ident,
208+ ( $this : ident / $def: ident ) . $field: ident,
175209 $glob_imports: ident [ $lookup: ident ] ,
176210 $def_import_type: ident
177- ) => {
178- match ( $existing. $field, $def. $field) {
179- ( None , Some ( _) ) => {
211+ ) => { {
212+ let existing = $this. $field. entry( $lookup. 1 . clone( ) ) ;
213+ match ( existing, $def. $field) {
214+ ( Entry :: Vacant ( entry) , Some ( _) ) => {
180215 match $def_import_type {
181216 ImportType :: Glob => {
182217 $glob_imports. $field. insert( $lookup. clone( ) ) ;
@@ -186,32 +221,42 @@ impl ItemScope {
186221 }
187222 }
188223
189- $existing. $field = $def. $field;
224+ if let Some ( fld) = $def. $field {
225+ entry. insert( fld) ;
226+ }
190227 $changed = true ;
191228 }
192- ( Some ( _ ) , Some ( _) )
229+ ( Entry :: Occupied ( mut entry ) , Some ( _) )
193230 if $glob_imports. $field. contains( & $lookup)
194231 && matches!( $def_import_type, ImportType :: Named ) =>
195232 {
196233 mark:: hit!( import_shadowed) ;
197234 $glob_imports. $field. remove( & $lookup) ;
198- $existing. $field = $def. $field;
235+ if let Some ( fld) = $def. $field {
236+ entry. insert( fld) ;
237+ }
199238 $changed = true ;
200239 }
201240 _ => { }
202241 }
203- } ;
242+ } } ;
204243 }
205244
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) ;
245+ check_changed ! ( changed, ( self / def) . types, glob_imports[ lookup] , def_import_type) ;
246+ check_changed ! ( changed, ( self / def) . values, glob_imports[ lookup] , def_import_type) ;
247+ check_changed ! ( changed, ( self / def) . macros, glob_imports[ lookup] , def_import_type) ;
248+
249+ if def. is_none ( ) {
250+ if self . unresolved . insert ( lookup. 1 ) {
251+ changed = true ;
252+ }
253+ }
209254
210255 changed
211256 }
212257
213258 pub ( crate ) fn resolutions < ' a > ( & ' a self ) -> impl Iterator < Item = ( Name , PerNs ) > + ' a {
214- self . visible . iter ( ) . map ( |( name, res) | ( name. clone ( ) , * res) )
259+ self . entries ( ) . map ( |( name, res) | ( name. clone ( ) , res) )
215260 }
216261
217262 pub ( crate ) fn collect_legacy_macros ( & self ) -> FxHashMap < Name , MacroDefId > {
0 commit comments