@@ -2893,25 +2893,26 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2893
2893
base : & ' tcx hir:: Expr ,
2894
2894
field : & Spanned < ast:: Name > ) {
2895
2895
check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
2896
- let expr_t = structurally_resolved_type ( fcx, expr. span ,
2897
- fcx. expr_ty ( base) ) ;
2898
- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2896
+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx. expr_ty ( base) ) ;
2897
+ let mut private_candidate = None ;
2899
2898
let ( _, autoderefs, field_ty) = autoderef ( fcx,
2900
2899
expr. span ,
2901
2900
expr_t,
2902
2901
|| Some ( base) ,
2903
2902
UnresolvedTypeAction :: Error ,
2904
2903
lvalue_pref,
2905
2904
|base_t, _| {
2906
- match base_t. sty {
2907
- ty:: TyStruct ( base_def, substs) => {
2908
- debug ! ( "struct named {:?}" , base_t) ;
2909
- base_def. struct_variant ( )
2910
- . find_field_named ( field. node )
2911
- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
2905
+ if let ty:: TyStruct ( base_def, substs) = base_t. sty {
2906
+ debug ! ( "struct named {:?}" , base_t) ;
2907
+ if let Some ( field) = base_def. struct_variant ( ) . find_field_named ( field. node ) {
2908
+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
2909
+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
2910
+ return Some ( field_ty) ;
2911
+ }
2912
+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
2912
2913
}
2913
- _ => None
2914
2914
}
2915
+ None
2915
2916
} ) ;
2916
2917
match field_ty {
2917
2918
Some ( field_ty) => {
@@ -2922,12 +2923,14 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2922
2923
None => { }
2923
2924
}
2924
2925
2925
- if field. node == special_idents:: invalid. name {
2926
+ if let Some ( ( did, field_ty) ) = private_candidate {
2927
+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
2928
+ let msg = format ! ( "field `{}` of struct `{}` is private" , field. node, struct_path) ;
2929
+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
2930
+ fcx. write_ty ( expr. id , field_ty) ;
2931
+ } else if field. node == special_idents:: invalid. name {
2926
2932
fcx. write_error ( expr. id ) ;
2927
- return ;
2928
- }
2929
-
2930
- if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
2933
+ } else if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
2931
2934
fcx. type_error_struct ( field. span ,
2932
2935
|actual| {
2933
2936
format ! ( "attempted to take value of method `{}` on type \
@@ -2938,6 +2941,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2938
2941
"maybe a `()` to call it is missing? \
2939
2942
If not, try an anonymous function")
2940
2943
. emit ( ) ;
2944
+ fcx. write_error ( expr. id ) ;
2941
2945
} else {
2942
2946
let mut err = fcx. type_error_struct (
2943
2947
expr. span ,
@@ -2953,9 +2957,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2953
2957
suggest_field_names ( & mut err, def. struct_variant ( ) , field, vec ! [ ] ) ;
2954
2958
}
2955
2959
err. emit ( ) ;
2960
+ fcx. write_error ( expr. id ) ;
2956
2961
}
2957
-
2958
- fcx. write_error ( expr. id ) ;
2959
2962
}
2960
2963
2961
2964
// displays hints about the closest matches in field names
@@ -2990,36 +2993,37 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2990
2993
base : & ' tcx hir:: Expr ,
2991
2994
idx : codemap:: Spanned < usize > ) {
2992
2995
check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
2993
- let expr_t = structurally_resolved_type ( fcx, expr. span ,
2994
- fcx . expr_ty ( base ) ) ;
2996
+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx . expr_ty ( base ) ) ;
2997
+ let mut private_candidate = None ;
2995
2998
let mut tuple_like = false ;
2996
- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2997
2999
let ( _, autoderefs, field_ty) = autoderef ( fcx,
2998
3000
expr. span ,
2999
3001
expr_t,
3000
3002
|| Some ( base) ,
3001
3003
UnresolvedTypeAction :: Error ,
3002
3004
lvalue_pref,
3003
3005
|base_t, _| {
3004
- match base_t. sty {
3005
- ty:: TyStruct ( base_def, substs) => {
3006
- tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3007
- if tuple_like {
3008
- debug ! ( "tuple struct named {:?}" , base_t) ;
3009
- base_def. struct_variant ( )
3010
- . fields
3011
- . get ( idx. node )
3012
- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
3013
- } else {
3014
- None
3015
- }
3016
- }
3006
+ let ( base_def, substs) = match base_t. sty {
3007
+ ty:: TyStruct ( base_def, substs) => ( base_def, substs) ,
3017
3008
ty:: TyTuple ( ref v) => {
3018
3009
tuple_like = true ;
3019
- if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
3010
+ return if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
3020
3011
}
3021
- _ => None
3012
+ _ => return None ,
3013
+ } ;
3014
+
3015
+ tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3016
+ if !tuple_like { return None }
3017
+
3018
+ debug ! ( "tuple struct named {:?}" , base_t) ;
3019
+ if let Some ( field) = base_def. struct_variant ( ) . fields . get ( idx. node ) {
3020
+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
3021
+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
3022
+ return Some ( field_ty) ;
3023
+ }
3024
+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
3022
3025
}
3026
+ None
3023
3027
} ) ;
3024
3028
match field_ty {
3025
3029
Some ( field_ty) => {
@@ -3029,6 +3033,15 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3029
3033
}
3030
3034
None => { }
3031
3035
}
3036
+
3037
+ if let Some ( ( did, field_ty) ) = private_candidate {
3038
+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
3039
+ let msg = format ! ( "field #{} of struct `{}` is private" , idx. node, struct_path) ;
3040
+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
3041
+ fcx. write_ty ( expr. id , field_ty) ;
3042
+ return ;
3043
+ }
3044
+
3032
3045
fcx. type_error_message (
3033
3046
expr. span ,
3034
3047
|actual| {
0 commit comments