@@ -1358,94 +1358,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13581358 // ...or if we already suggested that name because of `rustc_confusable` annotation.
13591359 && Some ( similar_candidate. name ) != confusable_suggested
13601360 {
1361- let def_kind = similar_candidate. kind . as_def_kind ( ) ;
1362- let an = self . tcx . def_kind_descr_article ( def_kind, similar_candidate. def_id ) ;
1363- // Methods are defined within the context of a struct and their first parameter
1364- // is always `self`, which represents the instance of the struct the method is
1365- // being called on Associated functions don’t take self as a parameter and they are
1366- // not methods because they don’t have an instance of the struct to work with.
1367- if def_kind == DefKind :: AssocFn {
1368- let ty_args = self . infcx . fresh_args_for_item ( span, similar_candidate. def_id ) ;
1369- let fn_sig = tcx. fn_sig ( similar_candidate. def_id ) . instantiate ( tcx, ty_args) ;
1370- let fn_sig =
1371- self . instantiate_binder_with_fresh_vars ( span, infer:: FnCall , fn_sig) ;
1372- if similar_candidate. fn_has_self_parameter {
1373- if let Some ( args) = args
1374- && fn_sig. inputs ( ) [ 1 ..] . len ( ) == args. len ( )
1375- {
1376- // We found a method with the same number of arguments as the method
1377- // call expression the user wrote.
1378- err. span_suggestion_verbose (
1379- span,
1380- format ! ( "there is {an} method with a similar name" ) ,
1381- similar_candidate. name ,
1382- Applicability :: MaybeIncorrect ,
1383- ) ;
1384- } else {
1385- // We found a method but either the expression is not a method call or
1386- // the argument count didn't match.
1387- err. span_help (
1388- tcx. def_span ( similar_candidate. def_id ) ,
1389- format ! (
1390- "there is {an} method `{}` with a similar name{}" ,
1391- similar_candidate. name,
1392- if let None = args {
1393- ""
1394- } else {
1395- ", but with different arguments"
1396- } ,
1397- ) ,
1398- ) ;
1399- }
1400- } else if let Some ( args) = args
1401- && fn_sig. inputs ( ) . len ( ) == args. len ( )
1402- {
1403- // We have fn call expression and the argument count match the associated
1404- // function we found.
1405- err. span_suggestion_verbose (
1406- span,
1407- format ! (
1408- "there is {an} {} with a similar name" ,
1409- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1410- ) ,
1411- similar_candidate. name ,
1412- Applicability :: MaybeIncorrect ,
1413- ) ;
1414- } else {
1415- err. span_help (
1416- tcx. def_span ( similar_candidate. def_id ) ,
1417- format ! (
1418- "there is {an} {} `{}` with a similar name" ,
1419- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1420- similar_candidate. name,
1421- ) ,
1422- ) ;
1423- }
1424- } else if let Mode :: Path = mode
1425- && args. unwrap_or ( & [ ] ) . is_empty ( )
1426- {
1427- // We have an associated item syntax and we found something that isn't an fn.
1428- err. span_suggestion_verbose (
1429- span,
1430- format ! (
1431- "there is {an} {} with a similar name" ,
1432- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1433- ) ,
1434- similar_candidate. name ,
1435- Applicability :: MaybeIncorrect ,
1436- ) ;
1437- } else {
1438- // The expression is a function or method call, but the item we found is an
1439- // associated const or type.
1440- err. span_help (
1441- tcx. def_span ( similar_candidate. def_id ) ,
1442- format ! (
1443- "there is {an} {} `{}` with a similar name" ,
1444- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1445- similar_candidate. name,
1446- ) ,
1447- ) ;
1448- }
1361+ self . find_likely_intended_associated_item (
1362+ & mut err,
1363+ similar_candidate,
1364+ span,
1365+ args,
1366+ mode,
1367+ ) ;
14491368 }
14501369 }
14511370 // If an appropriate error source is not found, check method chain for possible candiates
@@ -1497,6 +1416,100 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14971416 Some ( err)
14981417 }
14991418
1419+ fn find_likely_intended_associated_item (
1420+ & self ,
1421+ err : & mut Diagnostic ,
1422+ similar_candidate : ty:: AssocItem ,
1423+ span : Span ,
1424+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
1425+ mode : Mode ,
1426+ ) {
1427+ let tcx = self . tcx ;
1428+ let def_kind = similar_candidate. kind . as_def_kind ( ) ;
1429+ let an = self . tcx . def_kind_descr_article ( def_kind, similar_candidate. def_id ) ;
1430+ // Methods are defined within the context of a struct and their first parameter
1431+ // is always `self`, which represents the instance of the struct the method is
1432+ // being called on Associated functions don’t take self as a parameter and they are
1433+ // not methods because they don’t have an instance of the struct to work with.
1434+ if def_kind == DefKind :: AssocFn {
1435+ let ty_args = self . infcx . fresh_args_for_item ( span, similar_candidate. def_id ) ;
1436+ let fn_sig = tcx. fn_sig ( similar_candidate. def_id ) . instantiate ( tcx, ty_args) ;
1437+ let fn_sig = self . instantiate_binder_with_fresh_vars ( span, infer:: FnCall , fn_sig) ;
1438+ if similar_candidate. fn_has_self_parameter {
1439+ if let Some ( args) = args
1440+ && fn_sig. inputs ( ) [ 1 ..] . len ( ) == args. len ( )
1441+ {
1442+ // We found a method with the same number of arguments as the method
1443+ // call expression the user wrote.
1444+ err. span_suggestion_verbose (
1445+ span,
1446+ format ! ( "there is {an} method with a similar name" ) ,
1447+ similar_candidate. name ,
1448+ Applicability :: MaybeIncorrect ,
1449+ ) ;
1450+ } else {
1451+ // We found a method but either the expression is not a method call or
1452+ // the argument count didn't match.
1453+ err. span_help (
1454+ tcx. def_span ( similar_candidate. def_id ) ,
1455+ format ! (
1456+ "there is {an} method `{}` with a similar name{}" ,
1457+ similar_candidate. name,
1458+ if let None = args { "" } else { ", but with different arguments" } ,
1459+ ) ,
1460+ ) ;
1461+ }
1462+ } else if let Some ( args) = args
1463+ && fn_sig. inputs ( ) . len ( ) == args. len ( )
1464+ {
1465+ // We have fn call expression and the argument count match the associated
1466+ // function we found.
1467+ err. span_suggestion_verbose (
1468+ span,
1469+ format ! (
1470+ "there is {an} {} with a similar name" ,
1471+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1472+ ) ,
1473+ similar_candidate. name ,
1474+ Applicability :: MaybeIncorrect ,
1475+ ) ;
1476+ } else {
1477+ err. span_help (
1478+ tcx. def_span ( similar_candidate. def_id ) ,
1479+ format ! (
1480+ "there is {an} {} `{}` with a similar name" ,
1481+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1482+ similar_candidate. name,
1483+ ) ,
1484+ ) ;
1485+ }
1486+ } else if let Mode :: Path = mode
1487+ && args. unwrap_or ( & [ ] ) . is_empty ( )
1488+ {
1489+ // We have an associated item syntax and we found something that isn't an fn.
1490+ err. span_suggestion_verbose (
1491+ span,
1492+ format ! (
1493+ "there is {an} {} with a similar name" ,
1494+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1495+ ) ,
1496+ similar_candidate. name ,
1497+ Applicability :: MaybeIncorrect ,
1498+ ) ;
1499+ } else {
1500+ // The expression is a function or method call, but the item we found is an
1501+ // associated const or type.
1502+ err. span_help (
1503+ tcx. def_span ( similar_candidate. def_id ) ,
1504+ format ! (
1505+ "there is {an} {} `{}` with a similar name" ,
1506+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1507+ similar_candidate. name,
1508+ ) ,
1509+ ) ;
1510+ }
1511+ }
1512+
15001513 pub ( crate ) fn confusable_method_name (
15011514 & self ,
15021515 err : & mut Diagnostic ,
0 commit comments