@@ -2938,25 +2938,26 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2938
2938
base : & ' tcx hir:: Expr ,
2939
2939
field : & Spanned < ast:: Name > ) {
2940
2940
check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
2941
- let expr_t = structurally_resolved_type ( fcx, expr. span ,
2942
- fcx. expr_ty ( base) ) ;
2943
- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2941
+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx. expr_ty ( base) ) ;
2942
+ let mut private_candidate = None ;
2944
2943
let ( _, autoderefs, field_ty) = autoderef ( fcx,
2945
2944
expr. span ,
2946
2945
expr_t,
2947
2946
|| Some ( base) ,
2948
2947
UnresolvedTypeAction :: Error ,
2949
2948
lvalue_pref,
2950
2949
|base_t, _| {
2951
- match base_t. sty {
2952
- ty:: TyStruct ( base_def, substs) => {
2953
- debug ! ( "struct named {:?}" , base_t) ;
2954
- base_def. struct_variant ( )
2955
- . find_field_named ( field. node )
2956
- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
2950
+ if let ty:: TyStruct ( base_def, substs) = base_t. sty {
2951
+ debug ! ( "struct named {:?}" , base_t) ;
2952
+ if let Some ( field) = base_def. struct_variant ( ) . find_field_named ( field. node ) {
2953
+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
2954
+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
2955
+ return Some ( field_ty) ;
2956
+ }
2957
+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
2957
2958
}
2958
- _ => None
2959
2959
}
2960
+ None
2960
2961
} ) ;
2961
2962
match field_ty {
2962
2963
Some ( field_ty) => {
@@ -2967,12 +2968,14 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2967
2968
None => { }
2968
2969
}
2969
2970
2970
- if field. node == special_idents:: invalid. name {
2971
+ if let Some ( ( did, field_ty) ) = private_candidate {
2972
+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
2973
+ let msg = format ! ( "field `{}` of struct `{}` is private" , field. node, struct_path) ;
2974
+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
2975
+ fcx. write_ty ( expr. id , field_ty) ;
2976
+ } else if field. node == special_idents:: invalid. name {
2971
2977
fcx. write_error ( expr. id ) ;
2972
- return ;
2973
- }
2974
-
2975
- if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
2978
+ } else if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
2976
2979
fcx. type_error_struct ( field. span ,
2977
2980
|actual| {
2978
2981
format ! ( "attempted to take value of method `{}` on type \
@@ -2983,6 +2986,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2983
2986
"maybe a `()` to call it is missing? \
2984
2987
If not, try an anonymous function")
2985
2988
. emit ( ) ;
2989
+ fcx. write_error ( expr. id ) ;
2986
2990
} else {
2987
2991
let mut err = fcx. type_error_struct (
2988
2992
expr. span ,
@@ -2998,9 +3002,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2998
3002
suggest_field_names ( & mut err, def. struct_variant ( ) , field, vec ! [ ] ) ;
2999
3003
}
3000
3004
err. emit ( ) ;
3005
+ fcx. write_error ( expr. id ) ;
3001
3006
}
3002
-
3003
- fcx. write_error ( expr. id ) ;
3004
3007
}
3005
3008
3006
3009
// displays hints about the closest matches in field names
@@ -3035,36 +3038,37 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3035
3038
base : & ' tcx hir:: Expr ,
3036
3039
idx : codemap:: Spanned < usize > ) {
3037
3040
check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
3038
- let expr_t = structurally_resolved_type ( fcx, expr. span ,
3039
- fcx . expr_ty ( base ) ) ;
3041
+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx . expr_ty ( base ) ) ;
3042
+ let mut private_candidate = None ;
3040
3043
let mut tuple_like = false ;
3041
- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3042
3044
let ( _, autoderefs, field_ty) = autoderef ( fcx,
3043
3045
expr. span ,
3044
3046
expr_t,
3045
3047
|| Some ( base) ,
3046
3048
UnresolvedTypeAction :: Error ,
3047
3049
lvalue_pref,
3048
3050
|base_t, _| {
3049
- match base_t. sty {
3050
- ty:: TyStruct ( base_def, substs) => {
3051
- tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3052
- if tuple_like {
3053
- debug ! ( "tuple struct named {:?}" , base_t) ;
3054
- base_def. struct_variant ( )
3055
- . fields
3056
- . get ( idx. node )
3057
- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
3058
- } else {
3059
- None
3060
- }
3061
- }
3051
+ let ( base_def, substs) = match base_t. sty {
3052
+ ty:: TyStruct ( base_def, substs) => ( base_def, substs) ,
3062
3053
ty:: TyTuple ( ref v) => {
3063
3054
tuple_like = true ;
3064
- if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
3055
+ return if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
3065
3056
}
3066
- _ => None
3057
+ _ => return None ,
3058
+ } ;
3059
+
3060
+ tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3061
+ if !tuple_like { return None }
3062
+
3063
+ debug ! ( "tuple struct named {:?}" , base_t) ;
3064
+ if let Some ( field) = base_def. struct_variant ( ) . fields . get ( idx. node ) {
3065
+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
3066
+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
3067
+ return Some ( field_ty) ;
3068
+ }
3069
+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
3067
3070
}
3071
+ None
3068
3072
} ) ;
3069
3073
match field_ty {
3070
3074
Some ( field_ty) => {
@@ -3074,6 +3078,15 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3074
3078
}
3075
3079
None => { }
3076
3080
}
3081
+
3082
+ if let Some ( ( did, field_ty) ) = private_candidate {
3083
+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
3084
+ let msg = format ! ( "field `{}` of struct `{}` is private" , idx. node, struct_path) ;
3085
+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
3086
+ fcx. write_ty ( expr. id , field_ty) ;
3087
+ return ;
3088
+ }
3089
+
3077
3090
fcx. type_error_message (
3078
3091
expr. span ,
3079
3092
|actual| {
0 commit comments