@@ -1338,42 +1338,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1338
1338
item_name : Ident ,
1339
1339
) {
1340
1340
if let SelfSource :: MethodCall ( expr) = source
1341
- && let mod_id = self . tcx . parent_module ( expr. hir_id ) . to_def_id ( )
1342
- && let Some ( ( fields, substs) ) = self . get_field_candidates_considering_privacy ( span, actual, mod_id)
1341
+ && let mod_id = self . tcx . parent_module ( expr. hir_id ) . to_def_id ( )
1342
+ && let Some ( ( fields, substs) ) =
1343
+ self . get_field_candidates_considering_privacy ( span, actual, mod_id)
1343
1344
{
1344
1345
let call_expr = self . tcx . hir ( ) . expect_expr ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) ;
1345
- for candidate_field in fields {
1346
- if let Some ( field_path) = self . check_for_nested_field_satisfying (
1347
- span,
1348
- & |_, field_ty| {
1349
- self . lookup_probe (
1350
- span,
1351
- item_name,
1352
- field_ty,
1353
- call_expr,
1354
- ProbeScope :: AllTraits ,
1355
- )
1356
- . is_ok ( )
1357
- } ,
1358
- candidate_field,
1359
- substs,
1360
- vec ! [ ] ,
1361
- mod_id,
1362
- ) {
1363
- let field_path_str = field_path
1346
+
1347
+ let lang_items = self . tcx . lang_items ( ) ;
1348
+ let never_mention_traits = [
1349
+ lang_items. clone_trait ( ) ,
1350
+ lang_items. deref_trait ( ) ,
1351
+ lang_items. deref_mut_trait ( ) ,
1352
+ self . tcx . get_diagnostic_item ( sym:: AsRef ) ,
1353
+ self . tcx . get_diagnostic_item ( sym:: AsMut ) ,
1354
+ self . tcx . get_diagnostic_item ( sym:: Borrow ) ,
1355
+ self . tcx . get_diagnostic_item ( sym:: BorrowMut ) ,
1356
+ ] ;
1357
+ let candidate_fields: Vec < _ > = fields
1358
+ . filter_map ( |candidate_field| {
1359
+ self . check_for_nested_field_satisfying (
1360
+ span,
1361
+ & |_, field_ty| {
1362
+ self . lookup_probe (
1363
+ span,
1364
+ item_name,
1365
+ field_ty,
1366
+ call_expr,
1367
+ ProbeScope :: TraitsInScope ,
1368
+ )
1369
+ . map_or ( false , |pick| {
1370
+ !never_mention_traits
1371
+ . iter ( )
1372
+ . flatten ( )
1373
+ . any ( |def_id| self . tcx . parent ( pick. item . def_id ) == * def_id)
1374
+ } )
1375
+ } ,
1376
+ candidate_field,
1377
+ substs,
1378
+ vec ! [ ] ,
1379
+ mod_id,
1380
+ )
1381
+ } )
1382
+ . map ( |field_path| {
1383
+ field_path
1364
1384
. iter ( )
1365
1385
. map ( |id| id. name . to_ident_string ( ) )
1366
1386
. collect :: < Vec < String > > ( )
1367
- . join ( "." ) ;
1368
- debug ! ( "field_path_str: {:?}" , field_path_str) ;
1369
-
1370
- err. span_suggestion_verbose (
1371
- item_name. span . shrink_to_lo ( ) ,
1372
- "one of the expressions' fields has a method of the same name" ,
1373
- format ! ( "{field_path_str}." ) ,
1374
- Applicability :: MaybeIncorrect ,
1375
- ) ;
1376
- }
1387
+ . join ( "." )
1388
+ } )
1389
+ . collect ( ) ;
1390
+
1391
+ let len = candidate_fields. len ( ) ;
1392
+ if len > 0 {
1393
+ err. span_suggestions (
1394
+ item_name. span . shrink_to_lo ( ) ,
1395
+ format ! (
1396
+ "{} of the expressions' fields {} a method of the same name" ,
1397
+ if len > 1 { "some" } else { "one" } ,
1398
+ if len > 1 { "have" } else { "has" } ,
1399
+ ) ,
1400
+ candidate_fields. iter ( ) . map ( |path| format ! ( "{path}." ) ) ,
1401
+ Applicability :: MaybeIncorrect ,
1402
+ ) ;
1377
1403
}
1378
1404
}
1379
1405
}
0 commit comments