@@ -144,6 +144,7 @@ impl<'a> Resolver<'a> {
144
144
145
145
/// Attempts to resolve the supplied name in the given module for the given namespace.
146
146
/// If successful, returns the binding corresponding to the name.
147
+ /// Invariant: if `record_used` is `Some`, import resolution must be complete.
147
148
pub fn resolve_name_in_module ( & mut self ,
148
149
module : Module < ' a > ,
149
150
name : Name ,
@@ -159,32 +160,46 @@ impl<'a> Resolver<'a> {
159
160
_ => return Failed ( None ) , // This happens when there is a cycle of imports
160
161
} ;
161
162
162
- if let Some ( result) = self . try_result ( & resolution, ns, allow_private_imports) {
163
- // If the resolution doesn't depend on glob definability, check privacy and return.
164
- return result. and_then ( |binding| {
165
- if !allow_private_imports && binding. is_import ( ) && !binding. is_pseudo_public ( ) {
163
+ let is_disallowed_private_import = |binding : & NameBinding | {
164
+ !allow_private_imports && !binding. is_pseudo_public ( ) && binding. is_import ( )
165
+ } ;
166
+
167
+ if let Some ( span) = record_used {
168
+ if let Some ( binding) = resolution. binding {
169
+ if is_disallowed_private_import ( binding) {
166
170
return Failed ( None ) ;
167
171
}
168
- if let Some ( span) = record_used {
169
- self . record_use ( name, ns, binding) ;
170
- if !self . is_accessible ( binding. vis ) {
171
- self . privacy_errors . push ( PrivacyError ( span, name, binding) ) ;
172
- }
172
+ self . record_use ( name, ns, binding) ;
173
+ if !self . is_accessible ( binding. vis ) {
174
+ self . privacy_errors . push ( PrivacyError ( span, name, binding) ) ;
175
+ }
176
+ }
177
+
178
+ return resolution. binding . map ( Success ) . unwrap_or ( Failed ( None ) ) ;
179
+ }
180
+
181
+ // If the resolution doesn't depend on glob definability, check privacy and return.
182
+ if let Some ( result) = self . try_result ( & resolution, ns) {
183
+ return result. and_then ( |binding| {
184
+ if self . is_accessible ( binding. vis ) && !is_disallowed_private_import ( binding) {
185
+ Success ( binding)
186
+ } else {
187
+ Failed ( None )
173
188
}
174
- Success ( binding)
175
189
} ) ;
176
190
}
177
191
178
192
// Check if the globs are determined
179
193
for directive in module. globs . borrow ( ) . iter ( ) {
180
- if !allow_private_imports && directive. vis != ty:: Visibility :: Public { continue }
181
- if let Some ( target_module) = directive. target_module . get ( ) {
182
- let result = self . resolve_name_in_module ( target_module, name, ns, false , None ) ;
183
- if let Indeterminate = result {
194
+ if self . is_accessible ( directive. vis ) {
195
+ if let Some ( target_module) = directive. target_module . get ( ) {
196
+ let result = self . resolve_name_in_module ( target_module, name, ns, true , None ) ;
197
+ if let Indeterminate = result {
198
+ return Indeterminate ;
199
+ }
200
+ } else {
184
201
return Indeterminate ;
185
202
}
186
- } else {
187
- return Indeterminate ;
188
203
}
189
204
}
190
205
@@ -193,10 +208,7 @@ impl<'a> Resolver<'a> {
193
208
194
209
// Returns Some(the resolution of the name), or None if the resolution depends
195
210
// on whether more globs can define the name.
196
- fn try_result ( & mut self ,
197
- resolution : & NameResolution < ' a > ,
198
- ns : Namespace ,
199
- allow_private_imports : bool )
211
+ fn try_result ( & mut self , resolution : & NameResolution < ' a > , ns : Namespace )
200
212
-> Option < ResolveResult < & ' a NameBinding < ' a > > > {
201
213
match resolution. binding {
202
214
Some ( binding) if !binding. is_glob_import ( ) =>
@@ -206,17 +218,8 @@ impl<'a> Resolver<'a> {
206
218
207
219
// Check if a single import can still define the name.
208
220
match resolution. single_imports {
209
- SingleImports :: None => { } ,
210
221
SingleImports :: AtLeastOne => return Some ( Indeterminate ) ,
211
- SingleImports :: MaybeOne ( directive) => {
212
- // If (1) we don't allow private imports, (2) no public single import can define
213
- // the name, and (3) no public glob has defined the name, the resolution depends
214
- // on whether more globs can define the name.
215
- if !allow_private_imports && directive. vis != ty:: Visibility :: Public &&
216
- !resolution. binding . map ( NameBinding :: is_pseudo_public) . unwrap_or ( false ) {
217
- return None ;
218
- }
219
-
222
+ SingleImports :: MaybeOne ( directive) if self . is_accessible ( directive. vis ) => {
220
223
let target_module = match directive. target_module . get ( ) {
221
224
Some ( target_module) => target_module,
222
225
None => return Some ( Indeterminate ) ,
@@ -225,11 +228,12 @@ impl<'a> Resolver<'a> {
225
228
SingleImport { source, .. } => source,
226
229
GlobImport { .. } => unreachable ! ( ) ,
227
230
} ;
228
- match self . resolve_name_in_module ( target_module, name, ns, false , None ) {
231
+ match self . resolve_name_in_module ( target_module, name, ns, true , None ) {
229
232
Failed ( _) => { }
230
233
_ => return Some ( Indeterminate ) ,
231
234
}
232
235
}
236
+ SingleImports :: MaybeOne ( _) | SingleImports :: None => { } ,
233
237
}
234
238
235
239
resolution. binding . map ( Success )
@@ -389,7 +393,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
389
393
fn resolve_imports ( & mut self ) {
390
394
let mut i = 0 ;
391
395
let mut prev_num_indeterminates = self . indeterminate_imports . len ( ) + 1 ;
392
- let mut errors = Vec :: new ( ) ;
393
396
394
397
while self . indeterminate_imports . len ( ) < prev_num_indeterminates {
395
398
prev_num_indeterminates = self . indeterminate_imports . len ( ) ;
@@ -400,19 +403,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
400
403
401
404
for import in imports {
402
405
match self . resolve_import ( & import) {
403
- Failed ( err) => {
404
- let ( span, help) = match err {
405
- Some ( ( span, msg) ) => ( span, format ! ( ". {}" , msg) ) ,
406
- None => ( import. span , String :: new ( ) ) ,
407
- } ;
408
- errors. push ( ImportResolvingError {
409
- import_directive : import,
410
- span : span,
411
- help : help,
412
- } ) ;
413
- }
406
+ Failed ( _) => self . determined_imports . push ( import) ,
414
407
Indeterminate => self . indeterminate_imports . push ( import) ,
415
- Success ( ( ) ) => { }
408
+ Success ( ( ) ) => self . determined_imports . push ( import ) ,
416
409
}
417
410
}
418
411
@@ -423,6 +416,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
423
416
self . finalize_resolutions_in ( module) ;
424
417
}
425
418
419
+ let mut errors = Vec :: new ( ) ;
420
+ for i in 0 .. self . determined_imports . len ( ) {
421
+ let import = self . determined_imports [ i] ;
422
+ if let Failed ( err) = self . finalize_import ( import) {
423
+ let ( span, help) = match err {
424
+ Some ( ( span, msg) ) => ( span, format ! ( ". {}" , msg) ) ,
425
+ None => ( import. span , String :: new ( ) ) ,
426
+ } ;
427
+ errors. push ( ImportResolvingError {
428
+ import_directive : import,
429
+ span : span,
430
+ help : help,
431
+ } ) ;
432
+ }
433
+ }
434
+
426
435
// Report unresolved imports only if no hard error was already reported
427
436
// to avoid generating multiple errors on the same import.
428
437
if errors. len ( ) == 0 {
@@ -481,9 +490,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
481
490
482
491
let target_module = match directive. target_module . get ( ) {
483
492
Some ( module) => module,
484
- _ => match self . resolve_module_path ( & directive. module_path ,
485
- DontUseLexicalScope ,
486
- Some ( directive. span ) ) {
493
+ _ => match self . resolve_module_path ( & directive. module_path , DontUseLexicalScope , None ) {
487
494
Success ( module) => module,
488
495
Indeterminate => return Indeterminate ,
489
496
Failed ( err) => return Failed ( err) ,
@@ -494,27 +501,29 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
494
501
let ( source, target, value_result, type_result) = match directive. subclass {
495
502
SingleImport { source, target, ref value_result, ref type_result } =>
496
503
( source, target, value_result, type_result) ,
497
- GlobImport { .. } => return self . resolve_glob_import ( target_module, directive) ,
504
+ GlobImport { .. } => {
505
+ self . resolve_glob_import ( directive) ;
506
+ return Success ( ( ) ) ;
507
+ }
498
508
} ;
499
509
500
- let mut privacy_error = true ;
510
+ let mut indeterminate = false ;
501
511
for & ( ns, result) in & [ ( ValueNS , value_result) , ( TypeNS , type_result) ] {
502
- let was_determined = if let Err ( false ) = result. get ( ) {
512
+ if let Err ( false ) = result. get ( ) {
503
513
result. set ( {
504
- let span = Some ( directive. span ) ;
505
- match self . resolve_name_in_module ( target_module, source, ns, false , span) {
514
+ match self . resolve_name_in_module ( target_module, source, ns, false , None ) {
506
515
Success ( binding) => Ok ( binding) ,
507
516
Indeterminate => Err ( false ) ,
508
517
Failed ( _) => Err ( true ) ,
509
518
}
510
519
} ) ;
511
- false
512
520
} else {
513
- true
521
+ continue
514
522
} ;
515
523
516
524
match result. get ( ) {
517
- Err ( true ) if !was_determined => {
525
+ Err ( false ) => indeterminate = true ,
526
+ Err ( true ) => {
518
527
self . update_resolution ( module, target, ns, |_, resolution| {
519
528
resolution. single_imports . directive_failed ( )
520
529
} ) ;
@@ -529,26 +538,55 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
529
538
self . import_dummy_binding ( directive) ;
530
539
return Success ( ( ) ) ;
531
540
}
532
- Ok ( binding) if !self . is_accessible ( binding. vis ) => { }
533
- Ok ( binding) if !was_determined => {
541
+ Ok ( binding) => {
534
542
let imported_binding = self . import ( binding, directive) ;
535
543
let conflict = self . try_define ( module, target, ns, imported_binding) ;
536
544
if let Err ( old_binding) = conflict {
537
545
let binding = & self . import ( binding, directive) ;
538
546
self . report_conflict ( module, target, ns, binding, old_binding) ;
539
547
}
540
- privacy_error = false ;
541
548
}
542
- Ok ( _) => privacy_error = false ,
543
- _ => { }
544
549
}
545
550
}
546
551
547
- let ( value_result, type_result) = ( value_result. get ( ) , type_result. get ( ) ) ;
548
- match ( value_result, type_result) {
549
- ( Err ( false ) , _) | ( _, Err ( false ) ) => return Indeterminate ,
550
- ( Err ( true ) , Err ( true ) ) => {
551
- let resolutions = target_module. resolutions . borrow ( ) ;
552
+ if indeterminate { Indeterminate } else { Success ( ( ) ) }
553
+ }
554
+
555
+ fn finalize_import ( & mut self , directive : & ' b ImportDirective < ' b > ) -> ResolveResult < ( ) > {
556
+ self . set_current_module ( directive. parent ) ;
557
+
558
+ let ImportDirective { ref module_path, span, .. } = * directive;
559
+ let module_result = self . resolve_module_path ( & module_path, DontUseLexicalScope , Some ( span) ) ;
560
+ let module = match module_result {
561
+ Success ( module) => module,
562
+ Indeterminate => return Indeterminate ,
563
+ Failed ( err) => return Failed ( err) ,
564
+ } ;
565
+
566
+ let ( source, value_result, type_result) = match directive. subclass {
567
+ SingleImport { source, ref value_result, ref type_result, .. } =>
568
+ ( source, value_result. get ( ) , type_result. get ( ) ) ,
569
+ GlobImport { .. } if module. def_id ( ) == directive. parent . def_id ( ) => {
570
+ // Importing a module into itself is not allowed.
571
+ let msg = "Cannot glob-import a module into itself." . into ( ) ;
572
+ return Failed ( Some ( ( directive. span , msg) ) ) ;
573
+ }
574
+ GlobImport { .. } => return Success ( ( ) ) ,
575
+ } ;
576
+
577
+ for & ( ns, result) in & [ ( ValueNS , value_result) , ( TypeNS , type_result) ] {
578
+ if let Ok ( binding) = result {
579
+ self . record_use ( source, ns, binding) ;
580
+ }
581
+ }
582
+
583
+ if value_result. is_err ( ) && type_result. is_err ( ) {
584
+ let ( value_result, type_result) ;
585
+ value_result = self . resolve_name_in_module ( module, source, ValueNS , false , Some ( span) ) ;
586
+ type_result = self . resolve_name_in_module ( module, source, TypeNS , false , Some ( span) ) ;
587
+
588
+ return if let ( Failed ( _) , Failed ( _) ) = ( value_result, type_result) {
589
+ let resolutions = module. resolutions . borrow ( ) ;
552
590
let names = resolutions. iter ( ) . filter_map ( |( & ( ref name, _) , resolution) | {
553
591
if * name == source { return None ; } // Never suggest the same name
554
592
match * resolution. borrow ( ) {
@@ -561,29 +599,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
561
599
Some ( name) => format ! ( ". Did you mean to use `{}`?" , name) ,
562
600
None => "" . to_owned ( ) ,
563
601
} ;
564
- let module_str = module_to_string ( target_module ) ;
602
+ let module_str = module_to_string ( module ) ;
565
603
let msg = if & module_str == "???" {
566
604
format ! ( "There is no `{}` in the crate root{}" , source, lev_suggestion)
567
605
} else {
568
606
format ! ( "There is no `{}` in `{}`{}" , source, module_str, lev_suggestion)
569
607
} ;
570
- return Failed ( Some ( ( directive. span , msg) ) ) ;
571
- }
572
- _ => ( ) ,
573
- }
574
-
575
- if privacy_error {
576
- for & ( ns, result) in & [ ( ValueNS , value_result) , ( TypeNS , type_result) ] {
577
- let binding = match result { Ok ( binding) => binding, _ => continue } ;
578
- self . privacy_errors . push ( PrivacyError ( directive. span , source, binding) ) ;
579
- let imported_binding = self . import ( binding, directive) ;
580
- let _ = self . try_define ( module, target, ns, imported_binding) ;
608
+ Failed ( Some ( ( directive. span , msg) ) )
609
+ } else {
610
+ // `resolve_name_in_module` reported a privacy error.
611
+ self . import_dummy_binding ( directive) ;
612
+ Success ( ( ) )
581
613
}
582
614
}
583
615
584
616
match ( value_result, type_result) {
585
- ( Ok ( binding) , _) if !binding. pseudo_vis ( ) . is_at_least ( directive. vis , self ) &&
586
- self . is_accessible ( binding. vis ) => {
617
+ ( Ok ( binding) , _) if !binding. pseudo_vis ( ) . is_at_least ( directive. vis , self ) => {
587
618
let msg = format ! ( "`{}` is private, and cannot be reexported" , source) ;
588
619
let note_msg = format ! ( "consider marking `{}` as `pub` in the imported module" ,
589
620
source) ;
@@ -592,8 +623,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
592
623
. emit ( ) ;
593
624
}
594
625
595
- ( _, Ok ( binding) ) if !binding. pseudo_vis ( ) . is_at_least ( directive. vis , self ) &&
596
- self . is_accessible ( binding. vis ) => {
626
+ ( _, Ok ( binding) ) if !binding. pseudo_vis ( ) . is_at_least ( directive. vis , self ) => {
597
627
if binding. is_extern_crate ( ) {
598
628
let msg = format ! ( "extern crate `{}` is private, and cannot be reexported \
599
629
(error E0364), consider declaring with `pub`",
@@ -626,27 +656,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
626
656
return Success ( ( ) ) ;
627
657
}
628
658
629
- // Resolves a glob import. Note that this function cannot fail; it either
630
- // succeeds or bails out (as importing * from an empty module or a module
631
- // that exports nothing is valid). target_module is the module we are
632
- // actually importing, i.e., `foo` in `use foo::*`.
633
- fn resolve_glob_import ( & mut self , target_module : Module < ' b > , directive : & ' b ImportDirective < ' b > )
634
- -> ResolveResult < ( ) > {
659
+ fn resolve_glob_import ( & mut self , directive : & ' b ImportDirective < ' b > ) {
660
+ let target_module = directive. target_module . get ( ) . unwrap ( ) ;
661
+ self . populate_module_if_necessary ( target_module) ;
662
+
635
663
if let Some ( Def :: Trait ( _) ) = target_module. def {
636
664
self . session . span_err ( directive. span , "items in traits are not importable." ) ;
637
665
}
638
666
639
- let module = self . current_module ;
640
- if module. def_id ( ) == target_module. def_id ( ) {
641
- // This means we are trying to glob import a module into itself, and it is a no-go
642
- let msg = "Cannot glob-import a module into itself." . into ( ) ;
643
- return Failed ( Some ( ( directive. span , msg) ) ) ;
644
- }
645
- self . populate_module_if_necessary ( target_module) ;
646
-
647
- if let GlobImport { is_prelude : true } = directive. subclass {
667
+ let module = directive. parent ;
668
+ if target_module. def_id ( ) == module. def_id ( ) {
669
+ return ;
670
+ } else if let GlobImport { is_prelude : true } = directive. subclass {
648
671
self . prelude = Some ( target_module) ;
649
- return Success ( ( ) ) ;
672
+ return ;
650
673
}
651
674
652
675
// Add to target_module's glob_importers
@@ -669,9 +692,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
669
692
let resolution = PathResolution :: new ( Def :: Mod ( did) ) ;
670
693
self . def_map . insert ( directive. id , resolution) ;
671
694
}
672
-
673
- debug ! ( "(resolving glob import) successfully resolved import" ) ;
674
- return Success ( ( ) ) ;
675
695
}
676
696
677
697
// Miscellaneous post-processing, including recording reexports, reporting conflicts,
0 commit comments