@@ -2285,14 +2285,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2285
2285
// try to add a suggestion in case the field is a nested field of a field of the Adt
2286
2286
if let Some ( ( fields, substs) ) = self . get_field_candidates ( span, expr_t) {
2287
2287
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 (
2289
2289
span,
2290
- field,
2290
+ & |candidate_field , _| candidate_field . ident ( self . tcx ( ) ) == field,
2291
2291
candidate_field,
2292
2292
substs,
2293
2293
vec ! [ ] ,
2294
2294
self . tcx . parent_module ( id) . to_def_id ( ) ,
2295
2295
) {
2296
+ // field_path includes `field` that we're looking for, so pop it.
2297
+ field_path. pop ( ) ;
2298
+
2296
2299
let field_path_str = field_path
2297
2300
. iter ( )
2298
2301
. map ( |id| id. name . to_ident_string ( ) )
@@ -2312,7 +2315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2312
2315
err
2313
2316
}
2314
2317
2315
- fn get_field_candidates (
2318
+ crate fn get_field_candidates (
2316
2319
& self ,
2317
2320
span : Span ,
2318
2321
base_t : Ty < ' tcx > ,
@@ -2337,49 +2340,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2337
2340
2338
2341
/// This method is called after we have encountered a missing field error to recursively
2339
2342
/// search for the field
2340
- fn check_for_nested_field (
2343
+ crate fn check_for_nested_field_satisfying (
2341
2344
& self ,
2342
2345
span : Span ,
2343
- target_field : Ident ,
2346
+ matches : & impl Fn ( & ty :: FieldDef , Ty < ' tcx > ) -> bool ,
2344
2347
candidate_field : & ty:: FieldDef ,
2345
2348
subst : SubstsRef < ' tcx > ,
2346
2349
mut field_path : Vec < Ident > ,
2347
2350
id : DefId ,
2348
2351
) -> Option < Vec < Ident > > {
2349
2352
debug ! (
2350
- "check_for_nested_field (span: {:?}, candidate_field: {:?}, field_path: {:?}" ,
2353
+ "check_for_nested_field_satisfying (span: {:?}, candidate_field: {:?}, field_path: {:?}" ,
2351
2354
span, candidate_field, field_path
2352
2355
) ;
2353
2356
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 {
2357
2358
// For compile-time reasons and to avoid infinite recursion we only check for fields
2358
2359
// up to a depth of three
2359
2360
None
2360
2361
} else {
2361
2362
// recursively search fields of `candidate_field` if it's a ty::Adt
2362
-
2363
2363
field_path. push ( candidate_field. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) ) ;
2364
2364
let field_ty = candidate_field. ty ( self . tcx , subst) ;
2365
2365
if let Some ( ( nested_fields, subst) ) = self . get_field_candidates ( span, field_ty) {
2366
2366
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) {
2371
2369
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 (
2375
2371
span,
2376
- target_field ,
2372
+ matches ,
2377
2373
field,
2378
2374
subst,
2379
- field_path,
2375
+ field_path. clone ( ) ,
2380
2376
id,
2381
2377
) {
2382
- return Some ( path ) ;
2378
+ return Some ( field_path ) ;
2383
2379
}
2384
2380
}
2385
2381
}
0 commit comments