@@ -144,6 +144,7 @@ impl<'a> Resolver<'a> {
144144
145145 /// Attempts to resolve the supplied name in the given module for the given namespace.
146146 /// If successful, returns the binding corresponding to the name.
147+ /// Invariant: if `record_used` is `Some`, import resolution must be complete.
147148 pub fn resolve_name_in_module ( & mut self ,
148149 module : Module < ' a > ,
149150 name : Name ,
@@ -159,32 +160,46 @@ impl<'a> Resolver<'a> {
159160 _ => return Failed ( None ) , // This happens when there is a cycle of imports
160161 } ;
161162
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) {
166170 return Failed ( None ) ;
167171 }
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 )
173188 }
174- Success ( binding)
175189 } ) ;
176190 }
177191
178192 // Check if the globs are determined
179193 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 {
184201 return Indeterminate ;
185202 }
186- } else {
187- return Indeterminate ;
188203 }
189204 }
190205
@@ -193,10 +208,7 @@ impl<'a> Resolver<'a> {
193208
194209 // Returns Some(the resolution of the name), or None if the resolution depends
195210 // 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 )
200212 -> Option < ResolveResult < & ' a NameBinding < ' a > > > {
201213 match resolution. binding {
202214 Some ( binding) if !binding. is_glob_import ( ) =>
@@ -206,17 +218,8 @@ impl<'a> Resolver<'a> {
206218
207219 // Check if a single import can still define the name.
208220 match resolution. single_imports {
209- SingleImports :: None => { } ,
210221 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 ) => {
220223 let target_module = match directive. target_module . get ( ) {
221224 Some ( target_module) => target_module,
222225 None => return Some ( Indeterminate ) ,
@@ -225,11 +228,12 @@ impl<'a> Resolver<'a> {
225228 SingleImport { source, .. } => source,
226229 GlobImport { .. } => unreachable ! ( ) ,
227230 } ;
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 ) {
229232 Failed ( _) => { }
230233 _ => return Some ( Indeterminate ) ,
231234 }
232235 }
236+ SingleImports :: MaybeOne ( _) | SingleImports :: None => { } ,
233237 }
234238
235239 resolution. binding . map ( Success )
@@ -389,7 +393,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
389393 fn resolve_imports ( & mut self ) {
390394 let mut i = 0 ;
391395 let mut prev_num_indeterminates = self . indeterminate_imports . len ( ) + 1 ;
392- let mut errors = Vec :: new ( ) ;
393396
394397 while self . indeterminate_imports . len ( ) < prev_num_indeterminates {
395398 prev_num_indeterminates = self . indeterminate_imports . len ( ) ;
@@ -400,19 +403,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
400403
401404 for import in imports {
402405 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) ,
414407 Indeterminate => self . indeterminate_imports . push ( import) ,
415- Success ( ( ) ) => { }
408+ Success ( ( ) ) => self . determined_imports . push ( import ) ,
416409 }
417410 }
418411
@@ -423,6 +416,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
423416 self . finalize_resolutions_in ( module) ;
424417 }
425418
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+
426435 // Report unresolved imports only if no hard error was already reported
427436 // to avoid generating multiple errors on the same import.
428437 if errors. len ( ) == 0 {
@@ -481,9 +490,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
481490
482491 let target_module = match directive. target_module . get ( ) {
483492 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 ) {
487494 Success ( module) => module,
488495 Indeterminate => return Indeterminate ,
489496 Failed ( err) => return Failed ( err) ,
@@ -494,27 +501,29 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
494501 let ( source, target, value_result, type_result) = match directive. subclass {
495502 SingleImport { source, target, ref value_result, ref type_result } =>
496503 ( 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+ }
498508 } ;
499509
500- let mut privacy_error = true ;
510+ let mut indeterminate = false ;
501511 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 ( ) {
503513 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 ) {
506515 Success ( binding) => Ok ( binding) ,
507516 Indeterminate => Err ( false ) ,
508517 Failed ( _) => Err ( true ) ,
509518 }
510519 } ) ;
511- false
512520 } else {
513- true
521+ continue
514522 } ;
515523
516524 match result. get ( ) {
517- Err ( true ) if !was_determined => {
525+ Err ( false ) => indeterminate = true ,
526+ Err ( true ) => {
518527 self . update_resolution ( module, target, ns, |_, resolution| {
519528 resolution. single_imports . directive_failed ( )
520529 } ) ;
@@ -529,26 +538,55 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
529538 self . import_dummy_binding ( directive) ;
530539 return Success ( ( ) ) ;
531540 }
532- Ok ( binding) if !self . is_accessible ( binding. vis ) => { }
533- Ok ( binding) if !was_determined => {
541+ Ok ( binding) => {
534542 let imported_binding = self . import ( binding, directive) ;
535543 let conflict = self . try_define ( module, target, ns, imported_binding) ;
536544 if let Err ( old_binding) = conflict {
537545 let binding = & self . import ( binding, directive) ;
538546 self . report_conflict ( module, target, ns, binding, old_binding) ;
539547 }
540- privacy_error = false ;
541548 }
542- Ok ( _) => privacy_error = false ,
543- _ => { }
544549 }
545550 }
546551
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 ( ) ;
552590 let names = resolutions. iter ( ) . filter_map ( |( & ( ref name, _) , resolution) | {
553591 if * name == source { return None ; } // Never suggest the same name
554592 match * resolution. borrow ( ) {
@@ -561,29 +599,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
561599 Some ( name) => format ! ( ". Did you mean to use `{}`?" , name) ,
562600 None => "" . to_owned ( ) ,
563601 } ;
564- let module_str = module_to_string ( target_module ) ;
602+ let module_str = module_to_string ( module ) ;
565603 let msg = if & module_str == "???" {
566604 format ! ( "There is no `{}` in the crate root{}" , source, lev_suggestion)
567605 } else {
568606 format ! ( "There is no `{}` in `{}`{}" , source, module_str, lev_suggestion)
569607 } ;
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 ( ( ) )
581613 }
582614 }
583615
584616 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 ) => {
587618 let msg = format ! ( "`{}` is private, and cannot be reexported" , source) ;
588619 let note_msg = format ! ( "consider marking `{}` as `pub` in the imported module" ,
589620 source) ;
@@ -592,8 +623,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
592623 . emit ( ) ;
593624 }
594625
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 ) => {
597627 if binding. is_extern_crate ( ) {
598628 let msg = format ! ( "extern crate `{}` is private, and cannot be reexported \
599629 (error E0364), consider declaring with `pub`",
@@ -626,27 +656,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
626656 return Success ( ( ) ) ;
627657 }
628658
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+
635663 if let Some ( Def :: Trait ( _) ) = target_module. def {
636664 self . session . span_err ( directive. span , "items in traits are not importable." ) ;
637665 }
638666
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 {
648671 self . prelude = Some ( target_module) ;
649- return Success ( ( ) ) ;
672+ return ;
650673 }
651674
652675 // Add to target_module's glob_importers
@@ -669,9 +692,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
669692 let resolution = PathResolution :: new ( Def :: Mod ( did) ) ;
670693 self . def_map . insert ( directive. id , resolution) ;
671694 }
672-
673- debug ! ( "(resolving glob import) successfully resolved import" ) ;
674- return Success ( ( ) ) ;
675695 }
676696
677697 // Miscellaneous post-processing, including recording reexports, reporting conflicts,
0 commit comments