@@ -2692,33 +2692,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26922692 None
26932693 }
26942694
2695- // Check field access expressions
2695+ /// Check field access expressions, this works for both structs and tuples.
2696+ /// Returns the Ty of the field.
2697+ ///
2698+ /// ```not_rust
2699+ /// base.field
2700+ /// ^^^^^^^^^^ expr
2701+ /// ^^^^ base
2702+ /// ^^^^^ field
2703+ /// ```
26962704 fn check_expr_field (
26972705 & self ,
26982706 expr : & ' tcx hir:: Expr < ' tcx > ,
26992707 base : & ' tcx hir:: Expr < ' tcx > ,
27002708 field : Ident ,
2709+ // The expected type hint of the field.
27012710 expected : Expectation < ' tcx > ,
27022711 ) -> Ty < ' tcx > {
27032712 debug ! ( "check_field(expr: {:?}, base: {:?}, field: {:?})" , expr, base, field) ;
27042713 let base_ty = self . check_expr ( base) ;
27052714 let base_ty = self . structurally_resolve_type ( base. span , base_ty) ;
2715+
2716+ // Whether we are trying to access a private field. Used for error reporting.
27062717 let mut private_candidate = None ;
2718+
2719+ // Field expressions automatically deref
27072720 let mut autoderef = self . autoderef ( expr. span , base_ty) ;
27082721 while let Some ( ( deref_base_ty, _) ) = autoderef. next ( ) {
27092722 debug ! ( "deref_base_ty: {:?}" , deref_base_ty) ;
27102723 match deref_base_ty. kind ( ) {
27112724 ty:: Adt ( base_def, args) if !base_def. is_enum ( ) => {
27122725 debug ! ( "struct named {:?}" , deref_base_ty) ;
2713- let body_hir_id = self . tcx . local_def_id_to_hir_id ( self . body_id ) ;
2714- let ( ident, def_scope) =
2715- self . tcx . adjust_ident_and_get_scope ( field, base_def. did ( ) , body_hir_id) ;
2716-
27172726 // we don't care to report errors for a struct if the struct itself is tainted
27182727 if let Err ( guar) = base_def. non_enum_variant ( ) . has_errors ( ) {
27192728 return Ty :: new_error ( self . tcx ( ) , guar) ;
27202729 }
27212730
2731+ let fn_body_hir_id = self . tcx . local_def_id_to_hir_id ( self . body_id ) ;
2732+ let ( ident, def_scope) =
2733+ self . tcx . adjust_ident_and_get_scope ( field, base_def. did ( ) , fn_body_hir_id) ;
2734+
27222735 if let Some ( ( idx, field) ) = self . find_adt_field ( * base_def, ident) {
27232736 self . write_field_index ( expr. hir_id , idx) ;
27242737
@@ -2752,6 +2765,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27522765 _ => { }
27532766 }
27542767 }
2768+ // We failed to check the expression, report an error.
2769+
2770+ // Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
27552771 self . structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
27562772
27572773 if let Some ( ( adjustments, did) ) = private_candidate {
@@ -2776,6 +2792,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27762792 expr. hir_id ,
27772793 expected. only_has_type ( self ) ,
27782794 ) {
2795+ // If taking a method instead of calling it
27792796 self . ban_take_value_of_method ( expr, base_ty, field)
27802797 } else if !base_ty. is_primitive_ty ( ) {
27812798 self . ban_nonexisting_field ( field, base, expr, base_ty)
0 commit comments