@@ -2939,25 +2939,26 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29392939 base : & ' tcx hir:: Expr ,
29402940 field : & Spanned < ast:: Name > ) {
29412941 check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
2942- let expr_t = structurally_resolved_type ( fcx, expr. span ,
2943- fcx. expr_ty ( base) ) ;
2944- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2942+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx. expr_ty ( base) ) ;
2943+ let mut private_candidate = None ;
29452944 let ( _, autoderefs, field_ty) = autoderef ( fcx,
29462945 expr. span ,
29472946 expr_t,
29482947 || Some ( base) ,
29492948 UnresolvedTypeAction :: Error ,
29502949 lvalue_pref,
29512950 |base_t, _| {
2952- match base_t. sty {
2953- ty:: TyStruct ( base_def, substs) => {
2954- debug ! ( "struct named {:?}" , base_t) ;
2955- base_def. struct_variant ( )
2956- . find_field_named ( field. node )
2957- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
2951+ if let ty:: TyStruct ( base_def, substs) = base_t. sty {
2952+ debug ! ( "struct named {:?}" , base_t) ;
2953+ if let Some ( field) = base_def. struct_variant ( ) . find_field_named ( field. node ) {
2954+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
2955+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
2956+ return Some ( field_ty) ;
2957+ }
2958+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
29582959 }
2959- _ => None
29602960 }
2961+ None
29612962 } ) ;
29622963 match field_ty {
29632964 Some ( field_ty) => {
@@ -2968,12 +2969,14 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29682969 None => { }
29692970 }
29702971
2971- if field. node == special_idents:: invalid. name {
2972+ if let Some ( ( did, field_ty) ) = private_candidate {
2973+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
2974+ let msg = format ! ( "field `{}` of struct `{}` is private" , field. node, struct_path) ;
2975+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
2976+ fcx. write_ty ( expr. id , field_ty) ;
2977+ } else if field. node == special_idents:: invalid. name {
29722978 fcx. write_error ( expr. id ) ;
2973- return ;
2974- }
2975-
2976- if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
2979+ } else if method:: exists ( fcx, field. span , field. node , expr_t, expr. id ) {
29772980 fcx. type_error_struct ( field. span ,
29782981 |actual| {
29792982 format ! ( "attempted to take value of method `{}` on type \
@@ -2984,6 +2987,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29842987 "maybe a `()` to call it is missing? \
29852988 If not, try an anonymous function")
29862989 . emit ( ) ;
2990+ fcx. write_error ( expr. id ) ;
29872991 } else {
29882992 let mut err = fcx. type_error_struct (
29892993 expr. span ,
@@ -2999,9 +3003,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29993003 suggest_field_names ( & mut err, def. struct_variant ( ) , field, vec ! [ ] ) ;
30003004 }
30013005 err. emit ( ) ;
3006+ fcx. write_error ( expr. id ) ;
30023007 }
3003-
3004- fcx. write_error ( expr. id ) ;
30053008 }
30063009
30073010 // displays hints about the closest matches in field names
@@ -3036,36 +3039,37 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
30363039 base : & ' tcx hir:: Expr ,
30373040 idx : codemap:: Spanned < usize > ) {
30383041 check_expr_with_lvalue_pref ( fcx, base, lvalue_pref) ;
3039- let expr_t = structurally_resolved_type ( fcx, expr. span ,
3040- fcx . expr_ty ( base ) ) ;
3042+ let expr_t = structurally_resolved_type ( fcx, expr. span , fcx . expr_ty ( base ) ) ;
3043+ let mut private_candidate = None ;
30413044 let mut tuple_like = false ;
3042- // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
30433045 let ( _, autoderefs, field_ty) = autoderef ( fcx,
30443046 expr. span ,
30453047 expr_t,
30463048 || Some ( base) ,
30473049 UnresolvedTypeAction :: Error ,
30483050 lvalue_pref,
30493051 |base_t, _| {
3050- match base_t. sty {
3051- ty:: TyStruct ( base_def, substs) => {
3052- tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3053- if tuple_like {
3054- debug ! ( "tuple struct named {:?}" , base_t) ;
3055- base_def. struct_variant ( )
3056- . fields
3057- . get ( idx. node )
3058- . map ( |f| fcx. field_ty ( expr. span , f, substs) )
3059- } else {
3060- None
3061- }
3062- }
3052+ let ( base_def, substs) = match base_t. sty {
3053+ ty:: TyStruct ( base_def, substs) => ( base_def, substs) ,
30633054 ty:: TyTuple ( ref v) => {
30643055 tuple_like = true ;
3065- if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
3056+ return if idx. node < v. len ( ) { Some ( v[ idx. node ] ) } else { None }
30663057 }
3067- _ => None
3058+ _ => return None ,
3059+ } ;
3060+
3061+ tuple_like = base_def. struct_variant ( ) . is_tuple_struct ( ) ;
3062+ if !tuple_like { return None }
3063+
3064+ debug ! ( "tuple struct named {:?}" , base_t) ;
3065+ if let Some ( field) = base_def. struct_variant ( ) . fields . get ( idx. node ) {
3066+ let field_ty = fcx. field_ty ( expr. span , field, substs) ;
3067+ if field. vis == hir:: Public || fcx. private_item_is_visible ( base_def. did ) {
3068+ return Some ( field_ty) ;
3069+ }
3070+ private_candidate = Some ( ( base_def. did , field_ty) ) ;
30683071 }
3072+ None
30693073 } ) ;
30703074 match field_ty {
30713075 Some ( field_ty) => {
@@ -3075,6 +3079,15 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
30753079 }
30763080 None => { }
30773081 }
3082+
3083+ if let Some ( ( did, field_ty) ) = private_candidate {
3084+ let struct_path = fcx. tcx ( ) . item_path_str ( did) ;
3085+ let msg = format ! ( "field `{}` of struct `{}` is private" , idx. node, struct_path) ;
3086+ fcx. tcx ( ) . sess . span_err ( expr. span , & msg) ;
3087+ fcx. write_ty ( expr. id , field_ty) ;
3088+ return ;
3089+ }
3090+
30783091 fcx. type_error_message (
30793092 expr. span ,
30803093 |actual| {
@@ -3745,23 +3758,30 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
37453758 & ty_segments[ base_ty_end..] ) ;
37463759 let item_segment = path. segments . last ( ) . unwrap ( ) ;
37473760 let item_name = item_segment. identifier . name ;
3748- match method:: resolve_ufcs ( fcx, span, item_name, ty, node_id) {
3749- Ok ( def) => {
3750- // Write back the new resolution.
3751- fcx. ccx . tcx . def_map . borrow_mut ( )
3752- . insert ( node_id, def:: PathResolution {
3753- base_def : def,
3754- depth : 0
3755- } ) ;
3756- Some ( ( Some ( ty) , slice:: ref_slice ( item_segment) , def) )
3757- }
3761+ let def = match method:: resolve_ufcs ( fcx, span, item_name, ty, node_id) {
3762+ Ok ( def) => Some ( def) ,
37583763 Err ( error) => {
3764+ let def = match error {
3765+ method:: MethodError :: PrivateMatch ( def) => Some ( def) ,
3766+ _ => None ,
3767+ } ;
37593768 if item_name != special_idents:: invalid. name {
37603769 method:: report_error ( fcx, span, ty, item_name, None , error) ;
37613770 }
3762- fcx. write_error ( node_id) ;
3763- None
3771+ def
37643772 }
3773+ } ;
3774+
3775+ if let Some ( def) = def {
3776+ // Write back the new resolution.
3777+ fcx. ccx . tcx . def_map . borrow_mut ( ) . insert ( node_id, def:: PathResolution {
3778+ base_def : def,
3779+ depth : 0 ,
3780+ } ) ;
3781+ Some ( ( Some ( ty) , slice:: ref_slice ( item_segment) , def) )
3782+ } else {
3783+ fcx. write_error ( node_id) ;
3784+ None
37653785 }
37663786 }
37673787}
0 commit comments