Code change:
} } <del> fn no_such_field_err<T: Display>( </del> <ins> fn no_such_field_err( </ins> &self, <del> span: Span, field: T, expr_t: &ty::TyS<'_>, </del> <ins> field: Ident, expr_t: &'tcx ty::TyS<'tcx>, </ins> ) -> DiagnosticBuilder<'_> { <del> type_error_struct!( </del> <ins> let span = field.span; debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); let mut err = type_error_struct!( </ins> self.tcx().sess, <del> span, </del> <ins> field.span, </ins> expr_t, E0609, "no field `{}` on type `{}`", field, expr_t <del> ) </del> <ins> ); // try to add a suggestion in case the field is a nested field of a field of the Adt if let Some((fields, substs)) = self.get_field_candidates(span, &expr_t) { for candidate_field in fields.iter() { if let Some(field_path) = self.check_for_nested_field(span, field, candidate_field, substs, vec![]) { let field_path_str = field_path .iter() .map(|id| id.name.to_ident_string()) .collect::<Vec<String>>() .join("."); debug!("field_path_str: {:?}", field_path_str); err.span_suggestion_verbose( field.span.shrink_to_lo(), "one of the expressions' fields has a field of the same name", format!("{}.", field_path_str), Applicability::MaybeIncorrect, ); } } } err } fn get_field_candidates( &self, span: Span, base_t: Ty<'tcx>, ) -> Option<(&Vec<ty::FieldDef>, SubstsRef<'tcx>)> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t); let mut autoderef = self.autoderef(span, base_t); while let Some((base_t, _)) = autoderef.next() { match base_t.kind() { ty::Adt(base_def, substs) if !base_def.is_enum() => { let fields = &base_def.non_enum_variant().fields; // For compile-time reasons put a limit on number of fields we search if fields.len() > 100 { return None; } return Some((fields, substs)); } _ => {} } } None } /// This method is called after we have encountered a missing field error to recursively /// search for the field fn check_for_nested_field( &self, span: Span, target_field: Ident, candidate_field: &ty::FieldDef, subst: SubstsRef<'tcx>, mut field_path: Vec<Ident>, ) -> Option<Vec<Ident>> { debug!( "check_for_nested_field(span: {:?}, candidate_field: {:?}, field_path: {:?}", span, candidate_field, field_path ); if candidate_field.ident == target_field { Some(field_path) } else if field_path.len() > 3 { // For compile-time reasons and to avoid infinite recursion we only check for fields // up to a depth of three None } else { // recursively search fields of `candidate_field` if it's a ty::Adt field_path.push(candidate_field.ident.normalize_to_macros_2_0()); let field_ty = candidate_field.ty(self.tcx, subst); if let Some((nested_fields, _)) = self.get_field_candidates(span, &field_ty) { for field in nested_fields.iter() { let ident = field.ident.normalize_to_macros_2_0(); if ident == target_field { return Some(field_path); } else { let field_path = field_path.clone(); if let Some(path) = self.check_for_nested_field( span, target_field, field, subst, field_path, ) { return Some(path); } } } } None } </ins> } fn check_expr_index(

Related discussion:
text: I just encountered this output: We currently mention available fields when the field used isn't found. It would be nice if we peeked at the types for the available fields to see if any of them has any fields (including through deref) of the name we originally wanted. In this case, I would love to see the following output: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I'll work on this. claim
I was just about to open a PR when I saw that you claimed the issue. It's my fault for not claiming this issue myself obviously, so if you've already been investing time into this the issue its still yours, but if you haven't can I open a PR for this?
I've done nothing yet as I planned to work on this tomorrow morning, so this is yours :)
release-assignment
if you're still interested in contributing, it seems to me that might be similar in scope and section of the codebase you could work in.
Thank you.