@@ -2938,25 +2938,26 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29382938 base : & ' tcx hir:: Expr ,
29392939 field : & Spanned < ast:: Name > ) {
29402940 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 ;
29442943 let ( _, autoderefs, field_ty) = autoderef ( fcx,
29452944 expr. span ,
29462945 expr_t,
29472946 || Some ( base) ,
29482947 UnresolvedTypeAction :: Error ,
29492948 lvalue_pref,
29502949 |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) ) ;
29572958 }
2958- _ => None
29592959 }
2960+ None
29602961 } ) ;
29612962 match field_ty {
29622963 Some ( field_ty) => {
@@ -2967,12 +2968,14 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29672968 None => { }
29682969 }
29692970
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 {
29712977 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 ) {
29762979 fcx. type_error_struct ( field. span ,
29772980 |actual| {
29782981 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>,
29832986 "maybe a `()` to call it is missing? \
29842987 If not, try an anonymous function")
29852988 . emit ( ) ;
2989+ fcx. write_error ( expr. id ) ;
29862990 } else {
29872991 let mut err = fcx. type_error_struct (
29882992 expr. span ,
@@ -2998,9 +3002,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29983002 suggest_field_names ( & mut err, def. struct_variant ( ) , field, vec ! [ ] ) ;
29993003 }
30003004 err. emit ( ) ;
3005+ fcx. write_error ( expr. id ) ;
30013006 }
3002-
3003- fcx. write_error ( expr. id ) ;
30043007 }
30053008
30063009 // 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>,
30353038 base : & ' tcx hir:: Expr ,
30363039 idx : codemap:: Spanned < usize > ) {
30373040 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 ;
30403043 let mut tuple_like = false ;
3041- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
30423044 let ( _, autoderefs, field_ty) = autoderef ( fcx,
30433045 expr. span ,
30443046 expr_t,
30453047 || Some ( base) ,
30463048 UnresolvedTypeAction :: Error ,
30473049 lvalue_pref,
30483050 |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) ,
30623053 ty:: TyTuple ( ref v) => {
30633054 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 }
30653056 }
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) ) ;
30673070 }
3071+ None
30683072 } ) ;
30693073 match field_ty {
30703074 Some ( field_ty) => {
@@ -3074,6 +3078,15 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
30743078 }
30753079 None => { }
30763080 }
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+
30773090 fcx. type_error_message (
30783091 expr. span ,
30793092 |actual| {
0 commit comments