@@ -33,7 +33,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
3333use syntax_pos:: Span ;
3434
3535use std:: cell:: { Cell , RefCell } ;
36- use std:: { mem, ptr } ;
36+ use std:: mem;
3737
3838/// Contains data for specific types of import directives.
3939#[ derive( Clone , Debug ) ]
@@ -104,67 +104,20 @@ impl<'a> ImportDirective<'a> {
104104#[ derive( Clone , Default , Debug ) ]
105105/// Records information about the resolution of a name in a namespace of a module.
106106pub 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 > > ,
109110 /// The least shadowable known binding for this name, or None if there are no known bindings.
110111 pub binding : Option < & ' a NameBinding < ' a > > ,
111112 shadowed_glob : Option < & ' a NameBinding < ' a > > ,
112113}
113114
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-
161115impl < ' a > NameResolution < ' a > {
162116 // Returns the binding for the name if it is known or None if it not known.
163117 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 }
168121 } )
169122 }
170123}
@@ -227,58 +180,31 @@ impl<'a> Resolver<'a> {
227180 if usable { Ok ( binding) } else { Err ( Determined ) }
228181 } ;
229182
230- // Items and single imports are not shadowable.
183+ // Items and single imports are not shadowable, if we have one, then it's determined .
231184 if let Some ( binding) = resolution. binding {
232185 if !binding. is_glob_import ( ) {
233186 return check_usable ( self , binding) ;
234187 }
235188 }
236189
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 {
244201 SingleImport { source, .. } => source,
245202 _ => unreachable ! ( ) ,
246203 } ;
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 ) ,
280207 }
281- SingleImports :: None => { } ,
282208 }
283209
284210 let no_unresolved_invocations =
@@ -348,7 +274,7 @@ impl<'a> Resolver<'a> {
348274 SingleImport { target, type_ns_only, .. } => {
349275 self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
350276 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) ;
352278 } ) ;
353279 }
354280 // 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> {
640566 Err ( Undetermined ) => indeterminate = true ,
641567 Err ( Determined ) => {
642568 this. update_resolution ( parent, target, ns, |_, resolution| {
643- resolution. single_imports . directive_failed ( directive)
569+ resolution. single_imports . remove ( & ( directive as * const _ ) ) ;
644570 } ) ;
645571 }
646572 Ok ( binding) if !binding. is_importable ( ) => {
@@ -826,7 +752,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
826752 _ => Some ( & i. name ) ,
827753 }
828754 } ,
829- NameResolution { single_imports : SingleImports :: None , .. } => None ,
755+ NameResolution { ref single_imports, .. }
756+ if single_imports. is_empty ( ) => None ,
830757 _ => Some ( & i. name ) ,
831758 }
832759 } ) ;
0 commit comments