@@ -2535,15 +2535,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25352535 ) ;
25362536
25372537 // try to add a suggestion in case the field is a nested field of a field of the Adt
2538- if let Some ( ( fields, substs) ) = self . get_field_candidates ( span, expr_t) {
2539- for candidate_field in fields. iter ( ) {
2538+ let mod_id = self . tcx . parent_module ( id) . to_def_id ( ) ;
2539+ if let Some ( ( fields, substs) ) =
2540+ self . get_field_candidates_considering_privacy ( span, expr_t, mod_id)
2541+ {
2542+ for candidate_field in fields {
25402543 if let Some ( mut field_path) = self . check_for_nested_field_satisfying (
25412544 span,
25422545 & |candidate_field, _| candidate_field. ident ( self . tcx ( ) ) == field,
25432546 candidate_field,
25442547 substs,
25452548 vec ! [ ] ,
2546- self . tcx . parent_module ( id ) . to_def_id ( ) ,
2549+ mod_id ,
25472550 ) {
25482551 // field_path includes `field` that we're looking for, so pop it.
25492552 field_path. pop ( ) ;
@@ -2567,22 +2570,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25672570 err
25682571 }
25692572
2570- pub ( crate ) fn get_field_candidates (
2573+ pub ( crate ) fn get_field_candidates_considering_privacy (
25712574 & self ,
25722575 span : Span ,
2573- base_t : Ty < ' tcx > ,
2574- ) -> Option < ( & [ ty:: FieldDef ] , SubstsRef < ' tcx > ) > {
2575- debug ! ( "get_field_candidates(span: {:?}, base_t: {:?}" , span, base_t) ;
2576+ base_ty : Ty < ' tcx > ,
2577+ mod_id : DefId ,
2578+ ) -> Option < ( impl Iterator < Item = & ' tcx ty:: FieldDef > + ' tcx , SubstsRef < ' tcx > ) > {
2579+ debug ! ( "get_field_candidates(span: {:?}, base_t: {:?}" , span, base_ty) ;
25762580
2577- for ( base_t, _) in self . autoderef ( span, base_t ) {
2581+ for ( base_t, _) in self . autoderef ( span, base_ty ) {
25782582 match base_t. kind ( ) {
25792583 ty:: Adt ( base_def, substs) if !base_def. is_enum ( ) => {
2580- let fields = & base_def. non_enum_variant ( ) . fields ;
2581- // For compile-time reasons put a limit on number of fields we search
2582- if fields. len ( ) > 100 {
2583- return None ;
2584- }
2585- return Some ( ( fields, substs) ) ;
2584+ let tcx = self . tcx ;
2585+ return Some ( (
2586+ base_def
2587+ . non_enum_variant ( )
2588+ . fields
2589+ . iter ( )
2590+ . filter ( move |field| field. vis . is_accessible_from ( mod_id, tcx) )
2591+ // For compile-time reasons put a limit on number of fields we search
2592+ . take ( 100 ) ,
2593+ substs,
2594+ ) ) ;
25862595 }
25872596 _ => { }
25882597 }
@@ -2599,7 +2608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25992608 candidate_field : & ty:: FieldDef ,
26002609 subst : SubstsRef < ' tcx > ,
26012610 mut field_path : Vec < Ident > ,
2602- id : DefId ,
2611+ mod_id : DefId ,
26032612 ) -> Option < Vec < Ident > > {
26042613 debug ! (
26052614 "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}" ,
@@ -2615,20 +2624,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26152624 let field_ty = candidate_field. ty ( self . tcx , subst) ;
26162625 if matches ( candidate_field, field_ty) {
26172626 return Some ( field_path) ;
2618- } else if let Some ( ( nested_fields, subst) ) = self . get_field_candidates ( span, field_ty) {
2627+ } else if let Some ( ( nested_fields, subst) ) =
2628+ self . get_field_candidates_considering_privacy ( span, field_ty, mod_id)
2629+ {
26192630 // recursively search fields of `candidate_field` if it's a ty::Adt
26202631 for field in nested_fields {
2621- if field. vis . is_accessible_from ( id, self . tcx ) {
2622- if let Some ( field_path) = self . check_for_nested_field_satisfying (
2623- span,
2624- matches,
2625- field,
2626- subst,
2627- field_path. clone ( ) ,
2628- id,
2629- ) {
2630- return Some ( field_path) ;
2631- }
2632+ if let Some ( field_path) = self . check_for_nested_field_satisfying (
2633+ span,
2634+ matches,
2635+ field,
2636+ subst,
2637+ field_path. clone ( ) ,
2638+ mod_id,
2639+ ) {
2640+ return Some ( field_path) ;
26322641 }
26332642 }
26342643 }
0 commit comments