@@ -32,14 +32,31 @@ use syntax::codemap::Span;
32
32
use syntax:: util:: lev_distance:: find_best_match_for_name;
33
33
34
34
use std:: mem:: replace;
35
+ use std:: cell:: Cell ;
35
36
36
37
/// Contains data for specific types of import directives.
37
- #[ derive( Copy , Clone , Debug ) ]
38
+ #[ derive( Clone , Debug ) ]
38
39
pub enum ImportDirectiveSubclass {
39
- SingleImport ( Name /* target */ , Name /* source */ ) ,
40
+ SingleImport {
41
+ target : Name ,
42
+ source : Name ,
43
+ type_determined : Cell < bool > ,
44
+ value_determined : Cell < bool > ,
45
+ } ,
40
46
GlobImport ,
41
47
}
42
48
49
+ impl ImportDirectiveSubclass {
50
+ pub fn single ( target : Name , source : Name ) -> Self {
51
+ SingleImport {
52
+ target : target,
53
+ source : source,
54
+ type_determined : Cell :: new ( false ) ,
55
+ value_determined : Cell :: new ( false ) ,
56
+ }
57
+ }
58
+ }
59
+
43
60
/// Whether an import can be shadowed by another import.
44
61
#[ derive( Debug , PartialEq , Clone , Copy ) ]
45
62
pub enum Shadowable {
@@ -218,7 +235,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
218
235
fn import_resolving_error ( & self , e : ImportResolvingError < ' b > ) {
219
236
// If it's a single failed import then create a "fake" import
220
237
// resolution for it so that later resolve stages won't complain.
221
- if let SingleImport ( target, _ ) = e. import_directive . subclass {
238
+ if let SingleImport { target, .. } = e. import_directive . subclass {
222
239
let dummy_binding = self . resolver . new_name_binding ( NameBinding {
223
240
modifiers : DefModifiers :: PRELUDE ,
224
241
kind : NameBindingKind :: Def ( Def :: Err ) ,
@@ -304,15 +321,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
304
321
. and_then ( |containing_module| {
305
322
// We found the module that the target is contained
306
323
// within. Attempt to resolve the import within it.
307
- if let SingleImport ( target, source) = import_directive. subclass {
308
- self . resolve_single_import ( module_,
309
- containing_module,
310
- target,
311
- source,
312
- import_directive)
313
- } else {
314
- self . resolve_glob_import ( module_, containing_module, import_directive)
315
- }
324
+ self . resolve_import ( module_, containing_module, import_directive)
316
325
} )
317
326
. and_then ( |( ) | {
318
327
// Decrement the count of unresolved imports.
@@ -332,36 +341,53 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
332
341
} )
333
342
}
334
343
335
- fn resolve_single_import ( & mut self ,
336
- module_ : Module < ' b > ,
337
- target_module : Module < ' b > ,
338
- target : Name ,
339
- source : Name ,
340
- directive : & ImportDirective )
341
- -> ResolveResult < ( ) > {
342
- debug ! ( "(resolving single import) resolving `{}` = `{}::{}` from `{}` id {}" ,
343
- target,
344
- module_to_string( & target_module) ,
345
- source,
346
- module_to_string( module_) ,
347
- directive. id) ;
348
-
349
- // If this is a circular import, we temporarily count it as determined so that
350
- // it fails (as opposed to being indeterminate) when nothing else can define it.
351
- if target_module. def_id ( ) == module_. def_id ( ) && source == target {
352
- module_. decrement_outstanding_references_for ( target, ValueNS ) ;
353
- module_. decrement_outstanding_references_for ( target, TypeNS ) ;
354
- }
344
+ fn resolve_import ( & mut self ,
345
+ module_ : Module < ' b > ,
346
+ target_module : Module < ' b > ,
347
+ directive : & ImportDirective )
348
+ -> ResolveResult < ( ) > {
349
+ let ( source, target, value_determined, type_determined) = match directive. subclass {
350
+ SingleImport { source, target, ref value_determined, ref type_determined } =>
351
+ ( source, target, value_determined, type_determined) ,
352
+ GlobImport => return self . resolve_glob_import ( module_, target_module, directive) ,
353
+ } ;
355
354
356
355
// We need to resolve both namespaces for this to succeed.
357
- let value_result =
358
- self . resolver . resolve_name_in_module ( target_module, source, ValueNS , false , true ) ;
359
- let type_result =
360
- self . resolver . resolve_name_in_module ( target_module, source, TypeNS , false , true ) ;
361
-
362
- if target_module. def_id ( ) == module_. def_id ( ) && source == target {
363
- module_. increment_outstanding_references_for ( target, ValueNS ) ;
364
- module_. increment_outstanding_references_for ( target, TypeNS ) ;
356
+ let ( value_result, type_result) = {
357
+ let mut resolve_in_ns = |ns, determined : bool | {
358
+ // Temporarily count the directive as determined so that the resolution fails
359
+ // (as opposed to being indeterminate) when it can only be defined by the directive.
360
+ if !determined { module_. decrement_outstanding_references_for ( target, ns) }
361
+ let result =
362
+ self . resolver . resolve_name_in_module ( target_module, source, ns, false , true ) ;
363
+ if !determined { module_. increment_outstanding_references_for ( target, ns) }
364
+ result
365
+ } ;
366
+ ( resolve_in_ns ( ValueNS , value_determined. get ( ) ) ,
367
+ resolve_in_ns ( TypeNS , type_determined. get ( ) ) )
368
+ } ;
369
+
370
+ for & ( ns, result, determined) in & [ ( ValueNS , & value_result, value_determined) ,
371
+ ( TypeNS , & type_result, type_determined) ] {
372
+ if determined. get ( ) { continue }
373
+ if let Indeterminate = * result { continue }
374
+
375
+ determined. set ( true ) ;
376
+ if let Success ( binding) = * result {
377
+ if !binding. defined_with ( DefModifiers :: IMPORTABLE ) {
378
+ let msg = format ! ( "`{}` is not directly importable" , target) ;
379
+ span_err ! ( self . resolver. session, directive. span, E0253 , "{}" , & msg) ;
380
+ }
381
+
382
+ let privacy_error = if !self . resolver . is_visible ( binding, target_module) {
383
+ Some ( Box :: new ( PrivacyError ( directive. span , source, binding) ) )
384
+ } else {
385
+ None
386
+ } ;
387
+
388
+ self . define ( module_, target, ns, directive. import ( binding, privacy_error) ) ;
389
+ }
390
+ module_. decrement_outstanding_references_for ( target, ns) ;
365
391
}
366
392
367
393
match ( & value_result, & type_result) {
@@ -425,37 +451,22 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
425
451
_ => { }
426
452
}
427
453
454
+ // Report a privacy error here if all successful namespaces are privacy errors.
428
455
let mut privacy_error = None ;
429
- let mut report_privacy_error = true ;
430
- for & ( ns, result) in & [ ( ValueNS , & value_result) , ( TypeNS , & type_result) ] {
431
- if let Success ( binding) = * result {
432
- if !binding. defined_with ( DefModifiers :: IMPORTABLE ) {
433
- let msg = format ! ( "`{}` is not directly importable" , target) ;
434
- span_err ! ( self . resolver. session, directive. span, E0253 , "{}" , & msg) ;
435
- }
436
-
437
- privacy_error = if !self . resolver . is_visible ( binding, target_module) {
438
- Some ( Box :: new ( PrivacyError ( directive. span , source, binding) ) )
439
- } else {
440
- report_privacy_error = false ;
441
- None
442
- } ;
443
-
444
- self . define ( module_, target, ns, directive. import ( binding, privacy_error. clone ( ) ) ) ;
445
- }
446
- }
447
-
448
- if report_privacy_error { // then all successful namespaces are privacy errors
449
- // We report here so there is an error even if the imported name is not used
450
- self . resolver . privacy_errors . push ( * privacy_error. unwrap ( ) ) ;
456
+ for & ns in & [ ValueNS , TypeNS ] {
457
+ privacy_error = match module_. resolve_name ( target, ns, true ) {
458
+ Success ( & NameBinding {
459
+ kind : NameBindingKind :: Import { ref privacy_error, .. } , ..
460
+ } ) => privacy_error. as_ref ( ) . map ( |error| ( * * error) . clone ( ) ) ,
461
+ _ => continue ,
462
+ } ;
463
+ if privacy_error. is_none ( ) { break }
451
464
}
465
+ privacy_error. map ( |error| self . resolver . privacy_errors . push ( error) ) ;
452
466
453
467
// Record what this import resolves to for later uses in documentation,
454
468
// this may resolve to either a value or a type, but for documentation
455
469
// purposes it's good enough to just favor one over the other.
456
- module_. decrement_outstanding_references_for ( target, ValueNS ) ;
457
- module_. decrement_outstanding_references_for ( target, TypeNS ) ;
458
-
459
470
let def = match type_result. success ( ) . and_then ( NameBinding :: def) {
460
471
Some ( def) => def,
461
472
None => value_result. success ( ) . and_then ( NameBinding :: def) . unwrap ( ) ,
@@ -610,7 +621,7 @@ fn import_path_to_string(names: &[Name], subclass: ImportDirectiveSubclass) -> S
610
621
611
622
fn import_directive_subclass_to_string ( subclass : ImportDirectiveSubclass ) -> String {
612
623
match subclass {
613
- SingleImport ( _ , source) => source. to_string ( ) ,
624
+ SingleImport { source, .. } => source. to_string ( ) ,
614
625
GlobImport => "*" . to_string ( ) ,
615
626
}
616
627
}
0 commit comments