@@ -2285,14 +2285,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22852285 // try to add a suggestion in case the field is a nested field of a field of the Adt
22862286 if let Some ( ( fields, substs) ) = self . get_field_candidates ( span, expr_t) {
22872287 for candidate_field in fields. iter ( ) {
2288- if let Some ( field_path) = self . check_for_nested_field (
2288+ if let Some ( mut field_path) = self . check_for_nested_field_satisfying (
22892289 span,
2290- field,
2290+ & |candidate_field , _| candidate_field . ident ( self . tcx ( ) ) == field,
22912291 candidate_field,
22922292 substs,
22932293 vec ! [ ] ,
22942294 self . tcx . parent_module ( id) . to_def_id ( ) ,
22952295 ) {
2296+ // field_path includes `field` that we're looking for, so pop it.
2297+ field_path. pop ( ) ;
2298+
22962299 let field_path_str = field_path
22972300 . iter ( )
22982301 . map ( |id| id. name . to_ident_string ( ) )
@@ -2312,7 +2315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23122315 err
23132316 }
23142317
2315- fn get_field_candidates (
2318+ crate fn get_field_candidates (
23162319 & self ,
23172320 span : Span ,
23182321 base_t : Ty < ' tcx > ,
@@ -2337,49 +2340,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23372340
23382341 /// This method is called after we have encountered a missing field error to recursively
23392342 /// search for the field
2340- fn check_for_nested_field (
2343+ crate fn check_for_nested_field_satisfying (
23412344 & self ,
23422345 span : Span ,
2343- target_field : Ident ,
2346+ matches : & impl Fn ( & ty :: FieldDef , Ty < ' tcx > ) -> bool ,
23442347 candidate_field : & ty:: FieldDef ,
23452348 subst : SubstsRef < ' tcx > ,
23462349 mut field_path : Vec < Ident > ,
23472350 id : DefId ,
23482351 ) -> Option < Vec < Ident > > {
23492352 debug ! (
2350- "check_for_nested_field (span: {:?}, candidate_field: {:?}, field_path: {:?}" ,
2353+ "check_for_nested_field_satisfying (span: {:?}, candidate_field: {:?}, field_path: {:?}" ,
23512354 span, candidate_field, field_path
23522355 ) ;
23532356
2354- if candidate_field. ident ( self . tcx ) == target_field {
2355- Some ( field_path)
2356- } else if field_path. len ( ) > 3 {
2357+ if field_path. len ( ) > 3 {
23572358 // For compile-time reasons and to avoid infinite recursion we only check for fields
23582359 // up to a depth of three
23592360 None
23602361 } else {
23612362 // recursively search fields of `candidate_field` if it's a ty::Adt
2362-
23632363 field_path. push ( candidate_field. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) ) ;
23642364 let field_ty = candidate_field. ty ( self . tcx , subst) ;
23652365 if let Some ( ( nested_fields, subst) ) = self . get_field_candidates ( span, field_ty) {
23662366 for field in nested_fields. iter ( ) {
2367- let accessible = field. vis . is_accessible_from ( id, self . tcx ) ;
2368- if accessible {
2369- let ident = field. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) ;
2370- if ident == target_field {
2367+ if field. vis . is_accessible_from ( id, self . tcx ) {
2368+ if matches ( candidate_field, field_ty) {
23712369 return Some ( field_path) ;
2372- }
2373- let field_path = field_path. clone ( ) ;
2374- if let Some ( path) = self . check_for_nested_field (
2370+ } else if let Some ( field_path) = self . check_for_nested_field_satisfying (
23752371 span,
2376- target_field ,
2372+ matches ,
23772373 field,
23782374 subst,
2379- field_path,
2375+ field_path. clone ( ) ,
23802376 id,
23812377 ) {
2382- return Some ( path ) ;
2378+ return Some ( field_path ) ;
23832379 }
23842380 }
23852381 }
0 commit comments