@@ -2688,33 +2688,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26882688 None
26892689 }
26902690
2691- // Check field access expressions
2691+ /// Check field access expressions, this works for both structs and tuples.
2692+ /// Returns the Ty of the field.
2693+ ///
2694+ /// ```not_rust
2695+ /// base.field
2696+ /// ^^^^^^^^^^ expr
2697+ /// ^^^^ base
2698+ /// ^^^^^ field
2699+ /// ```
26922700 fn check_expr_field (
26932701 & self ,
26942702 expr : & ' tcx hir:: Expr < ' tcx > ,
26952703 base : & ' tcx hir:: Expr < ' tcx > ,
26962704 field : Ident ,
2705+ // The expected type hint of the field.
26972706 expected : Expectation < ' tcx > ,
26982707 ) -> Ty < ' tcx > {
26992708 debug ! ( "check_field(expr: {:?}, base: {:?}, field: {:?})" , expr, base, field) ;
27002709 let base_ty = self . check_expr ( base) ;
27012710 let base_ty = self . structurally_resolve_type ( base. span , base_ty) ;
2711+
2712+ // Whether we are trying to access a private field. Used for error reporting.
27022713 let mut private_candidate = None ;
2714+
2715+ // Field expressions automatically deref
27032716 let mut autoderef = self . autoderef ( expr. span , base_ty) ;
27042717 while let Some ( ( deref_base_ty, _) ) = autoderef. next ( ) {
27052718 debug ! ( "deref_base_ty: {:?}" , deref_base_ty) ;
27062719 match deref_base_ty. kind ( ) {
27072720 ty:: Adt ( base_def, args) if !base_def. is_enum ( ) => {
27082721 debug ! ( "struct named {:?}" , deref_base_ty) ;
2709- let body_hir_id = self . tcx . local_def_id_to_hir_id ( self . body_id ) ;
2710- let ( ident, def_scope) =
2711- self . tcx . adjust_ident_and_get_scope ( field, base_def. did ( ) , body_hir_id) ;
2712-
27132722 // we don't care to report errors for a struct if the struct itself is tainted
27142723 if let Err ( guar) = base_def. non_enum_variant ( ) . has_errors ( ) {
27152724 return Ty :: new_error ( self . tcx ( ) , guar) ;
27162725 }
27172726
2727+ let fn_body_hir_id = self . tcx . local_def_id_to_hir_id ( self . body_id ) ;
2728+ let ( ident, def_scope) =
2729+ self . tcx . adjust_ident_and_get_scope ( field, base_def. did ( ) , fn_body_hir_id) ;
2730+
27182731 if let Some ( ( idx, field) ) = self . find_adt_field ( * base_def, ident) {
27192732 self . write_field_index ( expr. hir_id , idx) ;
27202733
@@ -2748,6 +2761,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27482761 _ => { }
27492762 }
27502763 }
2764+ // We failed to check the expression, report an error.
2765+
2766+ // Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
27512767 self . structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
27522768
27532769 if let Some ( ( adjustments, did) ) = private_candidate {
@@ -2772,6 +2788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27722788 expr. hir_id ,
27732789 expected. only_has_type ( self ) ,
27742790 ) {
2791+ // If taking a method instead of calling it
27752792 self . ban_take_value_of_method ( expr, base_ty, field)
27762793 } else if !base_ty. is_primitive_ty ( ) {
27772794 self . ban_nonexisting_field ( field, base, expr, base_ty)
0 commit comments