@@ -49,6 +49,7 @@ crate struct ImportSuggestion {
4949 pub did : Option < DefId > ,
5050 pub descr : & ' static str ,
5151 pub path : Path ,
52+ pub accessible : bool ,
5253}
5354
5455/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -640,21 +641,32 @@ impl<'a> Resolver<'a> {
640641 let mut candidates = Vec :: new ( ) ;
641642 let mut seen_modules = FxHashSet :: default ( ) ;
642643 let not_local_module = crate_name. name != kw:: Crate ;
643- let mut worklist = vec ! [ ( start_module, Vec :: <ast:: PathSegment >:: new( ) , not_local_module) ] ;
644+ let mut worklist =
645+ vec ! [ ( start_module, Vec :: <ast:: PathSegment >:: new( ) , true , not_local_module) ] ;
644646
645- while let Some ( ( in_module, path_segments, in_module_is_extern) ) = worklist. pop ( ) {
647+ while let Some ( ( in_module, path_segments, accessible, in_module_is_extern) ) = worklist. pop ( )
648+ {
646649 // We have to visit module children in deterministic order to avoid
647650 // instabilities in reported imports (#43552).
648651 in_module. for_each_child ( self , |this, ident, ns, name_binding| {
649652 // avoid imports entirely
650653 if name_binding. is_import ( ) && !name_binding. is_extern_crate ( ) {
651654 return ;
652655 }
656+
653657 // avoid non-importable candidates as well
654658 if !name_binding. is_importable ( ) {
655659 return ;
656660 }
657661
662+ let child_accessible =
663+ accessible && this. is_accessible_from ( name_binding. vis , parent_scope. module ) ;
664+
665+ // do not venture inside inaccessible items of other crates
666+ if in_module_is_extern && !child_accessible {
667+ return ;
668+ }
669+
658670 // collect results based on the filter function
659671 // avoid suggesting anything from the same module in which we are resolving
660672 if ident. name == lookup_ident. name
@@ -673,22 +685,29 @@ impl<'a> Resolver<'a> {
673685
674686 segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
675687 let path = Path { span : name_binding. span , segments : segms } ;
676- // the entity is accessible in the following cases:
677- // 1. if it's defined in the same crate, it's always
678- // accessible (since private entities can be made public)
679- // 2. if it's defined in another crate, it's accessible
680- // only if both the module is public and the entity is
681- // declared as public (due to pruning, we don't explore
682- // outside crate private modules => no need to check this)
683- if !in_module_is_extern || name_binding. vis == ty:: Visibility :: Public {
684- let did = match res {
685- Res :: Def ( DefKind :: Ctor ( ..) , did) => this. parent ( did) ,
686- _ => res. opt_def_id ( ) ,
687- } ;
688- if candidates. iter ( ) . all ( |v : & ImportSuggestion | v. did != did) {
689- candidates. push ( ImportSuggestion { did, descr : res. descr ( ) , path } ) ;
688+ let did = match res {
689+ Res :: Def ( DefKind :: Ctor ( ..) , did) => this. parent ( did) ,
690+ _ => res. opt_def_id ( ) ,
691+ } ;
692+
693+ if child_accessible {
694+ // Remove invisible match if exists
695+ if let Some ( idx) = candidates
696+ . iter ( )
697+ . position ( |v : & ImportSuggestion | v. did == did && !v. accessible )
698+ {
699+ candidates. remove ( idx) ;
690700 }
691701 }
702+
703+ if candidates. iter ( ) . all ( |v : & ImportSuggestion | v. did != did) {
704+ candidates. push ( ImportSuggestion {
705+ did,
706+ descr : res. descr ( ) ,
707+ path,
708+ accessible : child_accessible,
709+ } ) ;
710+ }
692711 }
693712 }
694713
@@ -701,20 +720,22 @@ impl<'a> Resolver<'a> {
701720 let is_extern_crate_that_also_appears_in_prelude =
702721 name_binding. is_extern_crate ( ) && lookup_ident. span . rust_2018 ( ) ;
703722
704- let is_visible_to_user =
705- !in_module_is_extern || name_binding. vis == ty:: Visibility :: Public ;
706-
707- if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
708- // add the module to the lookup
723+ if !is_extern_crate_that_also_appears_in_prelude {
709724 let is_extern = in_module_is_extern || name_binding. is_extern_crate ( ) ;
725+ // add the module to the lookup
710726 if seen_modules. insert ( module. def_id ( ) . unwrap ( ) ) {
711- worklist. push ( ( module, path_segments, is_extern) ) ;
727+ worklist. push ( ( module, path_segments, child_accessible , is_extern) ) ;
712728 }
713729 }
714730 }
715731 } )
716732 }
717733
734+ // If only some candidates are accessible, take just them
735+ if !candidates. iter ( ) . all ( |v : & ImportSuggestion | !v. accessible ) {
736+ candidates = candidates. into_iter ( ) . filter ( |x| x. accessible ) . collect ( ) ;
737+ }
738+
718739 candidates
719740 }
720741
0 commit comments