@@ -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;
36
+ use std:: { mem, ptr } ;
37
37
38
38
/// Contains data for specific types of import directives.
39
39
#[ derive( Clone , Debug ) ]
@@ -89,6 +89,8 @@ enum SingleImports<'a> {
89
89
None ,
90
90
/// Only the given single import can define the name in the namespace.
91
91
MaybeOne ( & ' a ImportDirective < ' a > ) ,
92
+ /// Only one of these two single imports can define the name in the namespace.
93
+ MaybeTwo ( & ' a ImportDirective < ' a > , & ' a ImportDirective < ' a > ) ,
92
94
/// At least one single import will define the name in the namespace.
93
95
AtLeastOne ,
94
96
}
@@ -101,21 +103,28 @@ impl<'a> Default for SingleImports<'a> {
101
103
}
102
104
103
105
impl < ' a > SingleImports < ' a > {
104
- fn add_directive ( & mut self , directive : & ' a ImportDirective < ' a > ) {
106
+ fn add_directive ( & mut self , directive : & ' a ImportDirective < ' a > , use_extern_macros : bool ) {
105
107
match * self {
106
108
SingleImports :: None => * self = SingleImports :: MaybeOne ( directive) ,
107
- // If two single imports can define the name in the namespace, we can assume that at
108
- // least one of them will define it since otherwise both would have to define only one
109
- // namespace, leading to a duplicate error.
110
- SingleImports :: MaybeOne ( _) => * self = SingleImports :: AtLeastOne ,
109
+ SingleImports :: MaybeOne ( directive_one) => * self = if use_extern_macros {
110
+ SingleImports :: MaybeTwo ( directive_one, directive)
111
+ } else {
112
+ SingleImports :: AtLeastOne
113
+ } ,
114
+ // If three single imports can define the name in the namespace, we can assume that at
115
+ // least one of them will define it since otherwise we'd get duplicate errors in one of
116
+ // other namespaces.
117
+ SingleImports :: MaybeTwo ( ..) => * self = SingleImports :: AtLeastOne ,
111
118
SingleImports :: AtLeastOne => { }
112
119
} ;
113
120
}
114
121
115
- fn directive_failed ( & mut self ) {
122
+ fn directive_failed ( & mut self , dir : & ' a ImportDirective < ' a > ) {
116
123
match * self {
117
124
SingleImports :: None => unreachable ! ( ) ,
118
125
SingleImports :: MaybeOne ( _) => * self = SingleImports :: None ,
126
+ SingleImports :: MaybeTwo ( dir1, dir2) =>
127
+ * self = SingleImports :: MaybeOne ( if ptr:: eq ( dir1, dir) { dir1 } else { dir2 } ) ,
119
128
SingleImports :: AtLeastOne => { }
120
129
}
121
130
}
@@ -199,23 +208,50 @@ impl<'a> Resolver<'a> {
199
208
}
200
209
201
210
// Check if a single import can still define the name.
211
+ let resolve_single_import = |this : & mut Self , directive : & ' a ImportDirective < ' a > | {
212
+ let module = match directive. imported_module . get ( ) {
213
+ Some ( module) => module,
214
+ None => return false ,
215
+ } ;
216
+ let ident = match directive. subclass {
217
+ SingleImport { source, .. } => source,
218
+ _ => unreachable ! ( ) ,
219
+ } ;
220
+ match this. resolve_ident_in_module ( module, ident, ns, false , false , path_span) {
221
+ Err ( Determined ) => { }
222
+ _ => return false ,
223
+ }
224
+ true
225
+ } ;
202
226
match resolution. single_imports {
203
227
SingleImports :: AtLeastOne => return Err ( Undetermined ) ,
204
- SingleImports :: MaybeOne ( directive) if self . is_accessible ( directive. vis . get ( ) ) => {
205
- let module = match directive. imported_module . get ( ) {
206
- Some ( module) => module,
207
- None => return Err ( Undetermined ) ,
208
- } ;
209
- let ident = match directive. subclass {
210
- SingleImport { source, .. } => source,
211
- _ => unreachable ! ( ) ,
212
- } ;
213
- match self . resolve_ident_in_module ( module, ident, ns, false , false , path_span) {
214
- Err ( Determined ) => { }
215
- _ => return Err ( Undetermined ) ,
228
+ SingleImports :: MaybeOne ( directive) => {
229
+ let accessible = self . is_accessible ( directive. vis . get ( ) ) ;
230
+ if accessible {
231
+ if !resolve_single_import ( self , directive) {
232
+ return Err ( Undetermined )
233
+ }
234
+ }
235
+ }
236
+ SingleImports :: MaybeTwo ( directive1, directive2) => {
237
+ let accessible1 = self . is_accessible ( directive1. vis . get ( ) ) ;
238
+ let accessible2 = self . is_accessible ( directive2. vis . get ( ) ) ;
239
+ if accessible1 && accessible2 {
240
+ if !resolve_single_import ( self , directive1) &&
241
+ !resolve_single_import ( self , directive2) {
242
+ return Err ( Undetermined )
243
+ }
244
+ } else if accessible1 {
245
+ if !resolve_single_import ( self , directive1) {
246
+ return Err ( Undetermined )
247
+ }
248
+ } else {
249
+ if !resolve_single_import ( self , directive2) {
250
+ return Err ( Undetermined )
251
+ }
216
252
}
217
253
}
218
- SingleImports :: MaybeOne ( _ ) | SingleImports :: None => { } ,
254
+ SingleImports :: None => { } ,
219
255
}
220
256
221
257
let no_unresolved_invocations =
@@ -281,7 +317,7 @@ impl<'a> Resolver<'a> {
281
317
SingleImport { target, .. } => {
282
318
self . per_ns ( |this, ns| {
283
319
let mut resolution = this. resolution ( current_module, target, ns) . borrow_mut ( ) ;
284
- resolution. single_imports . add_directive ( directive) ;
320
+ resolution. single_imports . add_directive ( directive, this . use_extern_macros ) ;
285
321
} ) ;
286
322
}
287
323
// We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -575,7 +611,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
575
611
Err ( Undetermined ) => indeterminate = true ,
576
612
Err ( Determined ) => {
577
613
this. update_resolution ( parent, target, ns, |_, resolution| {
578
- resolution. single_imports . directive_failed ( )
614
+ resolution. single_imports . directive_failed ( directive )
579
615
} ) ;
580
616
}
581
617
Ok ( binding) if !binding. is_importable ( ) => {
0 commit comments