@@ -33,7 +33,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
33
33
use syntax_pos:: Span ;
34
34
35
35
use std:: cell:: { Cell , RefCell } ;
36
- use std:: { mem, ptr } ;
36
+ use std:: mem;
37
37
38
38
/// Contains data for specific types of import directives.
39
39
#[ derive( Clone , Debug ) ]
@@ -104,67 +104,20 @@ impl<'a> ImportDirective<'a> {
104
104
#[ derive( Clone , Default , Debug ) ]
105
105
/// Records information about the resolution of a name in a namespace of a module.
106
106
pub struct NameResolution < ' a > {
107
- /// The single imports that define the name in the namespace.
108
- single_imports : SingleImports < ' a > ,
107
+ /// Single imports that may define the name in the namespace.
108
+ /// Import directives are arena-allocated, so it's ok to use pointers as keys, they are stable.
109
+ single_imports : FxHashSet < * const ImportDirective < ' a > > ,
109
110
/// The least shadowable known binding for this name, or None if there are no known bindings.
110
111
pub binding : Option < & ' a NameBinding < ' a > > ,
111
112
shadowed_glob : Option < & ' a NameBinding < ' a > > ,
112
113
}
113
114
114
- #[ derive( Clone , Debug ) ]
115
- enum SingleImports < ' a > {
116
- /// No single imports can define the name in the namespace.
117
- None ,
118
- /// Only the given single import can define the name in the namespace.
119
- MaybeOne ( & ' a ImportDirective < ' a > ) ,
120
- /// Only one of these two single imports can define the name in the namespace.
121
- MaybeTwo ( & ' a ImportDirective < ' a > , & ' a ImportDirective < ' a > ) ,
122
- /// At least one single import will define the name in the namespace.
123
- AtLeastOne ,
124
- }
125
-
126
- impl < ' a > Default for SingleImports < ' a > {
127
- /// Creates a `SingleImports<'a>` of None type.
128
- fn default ( ) -> Self {
129
- SingleImports :: None
130
- }
131
- }
132
-
133
- impl < ' a > SingleImports < ' a > {
134
- fn add_directive ( & mut self , directive : & ' a ImportDirective < ' a > , use_extern_macros : bool ) {
135
- match * self {
136
- SingleImports :: None => * self = SingleImports :: MaybeOne ( directive) ,
137
- SingleImports :: MaybeOne ( directive_one) => * self = if use_extern_macros {
138
- SingleImports :: MaybeTwo ( directive_one, directive)
139
- } else {
140
- SingleImports :: AtLeastOne
141
- } ,
142
- // If three single imports can define the name in the namespace, we can assume that at
143
- // least one of them will define it since otherwise we'd get duplicate errors in one of
144
- // other namespaces.
145
- SingleImports :: MaybeTwo ( ..) => * self = SingleImports :: AtLeastOne ,
146
- SingleImports :: AtLeastOne => { }
147
- } ;
148
- }
149
-
150
- fn directive_failed ( & mut self , dir : & ' a ImportDirective < ' a > ) {
151
- match * self {
152
- SingleImports :: None => unreachable ! ( ) ,
153
- SingleImports :: MaybeOne ( _) => * self = SingleImports :: None ,
154
- SingleImports :: MaybeTwo ( dir1, dir2) =>
155
- * self = SingleImports :: MaybeOne ( if ptr:: eq ( dir1, dir) { dir1 } else { dir2 } ) ,
156
- SingleImports :: AtLeastOne => { }
157
- }
158
- }
159
- }
160
-
161
115
impl < ' a > NameResolution < ' a > {
162
116
// Returns the binding for the name if it is known or None if it not known.
163
117
fn binding ( & self ) -> Option < & ' a NameBinding < ' a > > {
164
- self . binding . and_then ( |binding| match self . single_imports {
165
- SingleImports :: None => Some ( binding) ,
166
- _ if !binding. is_glob_import ( ) => Some ( binding) ,
167
- _ => None , // The binding could be shadowed by a single import, so it is not known.
118
+ self . binding . and_then ( |binding| {
119
+ if !binding. is_glob_import ( ) ||
120
+ self . single_imports . is_empty ( ) { Some ( binding) } else { None }
168
121
} )
169
122
}
170
123
}
@@ -227,58 +180,31 @@ impl<'a> Resolver<'a> {
227
180
if usable { Ok ( binding) } else { Err ( Determined ) }
228
181
} ;
229
182
230
- // Items and single imports are not shadowable.
183
+ // Items and single imports are not shadowable, if we have one, then it's determined .
231
184
if let Some ( binding) = resolution. binding {
232
185
if !binding. is_glob_import ( ) {
233
186
return check_usable ( self , binding) ;
234
187
}
235
188
}
236
189
237
- // Check if a single import can still define the name.
238
- let resolve_single_import = |this : & mut Self , directive : & ' a ImportDirective < ' a > | {
239
- let module = match directive. imported_module . get ( ) {
240
- Some ( module) => module,
241
- None => return false ,
242
- } ;
243
- let ident = match directive. subclass {
190
+ // From now on we either have a glob resolution or no resolution.
191
+
192
+ // Check if one of single imports can still define the name,
193
+ // if it can then our result is not determined and can be invalidated.
194
+ for single_import in & resolution. single_imports {
195
+ let single_import = unsafe { & * * single_import } ;
196
+ if !self . is_accessible ( single_import. vis . get ( ) ) {
197
+ continue ;
198
+ }
199
+ let module = unwrap_or ! ( single_import. imported_module. get( ) , return Err ( Undetermined ) ) ;
200
+ let ident = match single_import. subclass {
244
201
SingleImport { source, .. } => source,
245
202
_ => unreachable ! ( ) ,
246
203
} ;
247
- match this. resolve_ident_in_module ( module, ident, ns, false , path_span) {
248
- Err ( Determined ) => { }
249
- _ => return false ,
250
- }
251
- true
252
- } ;
253
- match resolution. single_imports {
254
- SingleImports :: AtLeastOne => return Err ( Undetermined ) ,
255
- SingleImports :: MaybeOne ( directive) => {
256
- let accessible = self . is_accessible ( directive. vis . get ( ) ) ;
257
- if accessible {
258
- if !resolve_single_import ( self , directive) {
259
- return Err ( Undetermined )
260
- }
261
- }
262
- }
263
- SingleImports :: MaybeTwo ( directive1, directive2) => {
264
- let accessible1 = self . is_accessible ( directive1. vis . get ( ) ) ;
265
- let accessible2 = self . is_accessible ( directive2. vis . get ( ) ) ;
266
- if accessible1 && accessible2 {
267
- if !resolve_single_import ( self , directive1) &&
268
- !resolve_single_import ( self , directive2) {
269
- return Err ( Undetermined )
270
- }
271
- } else if accessible1 {
272
- if !resolve_single_import ( self , directive1) {
273
- return Err ( Undetermined )
274
- }
275
- } else {
276
- if !resolve_single_import ( self , directive2) {
277
- return Err ( Undetermined )
278
- }
279
- }
204
+ match self . resolve_ident_in_module ( module, ident, ns, false , path_span) {
205
+ Err ( Determined ) => continue ,
206
+ Ok ( _) | Err ( Undetermined ) => return Err ( Undetermined ) ,
280
207
}
281
- SingleImports :: None => { } ,
282
208
}
283
209
284
210
let no_unresolved_invocations =
@@ -348,7 +274,7 @@ impl<'a> Resolver<'a> {
348
274
SingleImport { target, type_ns_only, .. } => {
349
275
self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
350
276
let mut resolution = this. resolution ( current_module, target, ns) . borrow_mut ( ) ;
351
- resolution. single_imports . add_directive ( directive, this . use_extern_macros ) ;
277
+ resolution. single_imports . insert ( directive) ;
352
278
} ) ;
353
279
}
354
280
// We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -640,7 +566,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
640
566
Err ( Undetermined ) => indeterminate = true ,
641
567
Err ( Determined ) => {
642
568
this. update_resolution ( parent, target, ns, |_, resolution| {
643
- resolution. single_imports . directive_failed ( directive)
569
+ resolution. single_imports . remove ( & ( directive as * const _ ) ) ;
644
570
} ) ;
645
571
}
646
572
Ok ( binding) if !binding. is_importable ( ) => {
@@ -826,7 +752,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
826
752
_ => Some ( & i. name ) ,
827
753
}
828
754
} ,
829
- NameResolution { single_imports : SingleImports :: None , .. } => None ,
755
+ NameResolution { ref single_imports, .. }
756
+ if single_imports. is_empty ( ) => None ,
830
757
_ => Some ( & i. name ) ,
831
758
}
832
759
} ) ;
0 commit comments