@@ -49,6 +49,7 @@ crate struct ImportSuggestion {
49
49
pub did : Option < DefId > ,
50
50
pub descr : & ' static str ,
51
51
pub path : Path ,
52
+ pub accessible : bool ,
52
53
}
53
54
54
55
/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -640,21 +641,32 @@ impl<'a> Resolver<'a> {
640
641
let mut candidates = Vec :: new ( ) ;
641
642
let mut seen_modules = FxHashSet :: default ( ) ;
642
643
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) ] ;
644
646
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
+ {
646
649
// We have to visit module children in deterministic order to avoid
647
650
// instabilities in reported imports (#43552).
648
651
in_module. for_each_child ( self , |this, ident, ns, name_binding| {
649
652
// avoid imports entirely
650
653
if name_binding. is_import ( ) && !name_binding. is_extern_crate ( ) {
651
654
return ;
652
655
}
656
+
653
657
// avoid non-importable candidates as well
654
658
if !name_binding. is_importable ( ) {
655
659
return ;
656
660
}
657
661
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
+
658
670
// collect results based on the filter function
659
671
// avoid suggesting anything from the same module in which we are resolving
660
672
if ident. name == lookup_ident. name
@@ -673,22 +685,29 @@ impl<'a> Resolver<'a> {
673
685
674
686
segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
675
687
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) ;
690
700
}
691
701
}
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
+ }
692
711
}
693
712
}
694
713
@@ -701,20 +720,22 @@ impl<'a> Resolver<'a> {
701
720
let is_extern_crate_that_also_appears_in_prelude =
702
721
name_binding. is_extern_crate ( ) && lookup_ident. span . rust_2018 ( ) ;
703
722
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 {
709
724
let is_extern = in_module_is_extern || name_binding. is_extern_crate ( ) ;
725
+ // add the module to the lookup
710
726
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) ) ;
712
728
}
713
729
}
714
730
}
715
731
} )
716
732
}
717
733
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
+
718
739
candidates
719
740
}
720
741
0 commit comments