@@ -1256,94 +1256,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12561256 // ...or if we already suggested that name because of `rustc_confusable` annotation.
12571257 && Some ( similar_candidate. name ) != confusable_suggested
12581258 {
1259- let def_kind = similar_candidate. kind . as_def_kind ( ) ;
1260- let an = self . tcx . def_kind_descr_article ( def_kind, similar_candidate. def_id ) ;
1261- // Methods are defined within the context of a struct and their first parameter
1262- // is always `self`, which represents the instance of the struct the method is
1263- // being called on Associated functions don’t take self as a parameter and they are
1264- // not methods because they don’t have an instance of the struct to work with.
1265- if def_kind == DefKind :: AssocFn {
1266- let ty_args = self . infcx . fresh_args_for_item ( span, similar_candidate. def_id ) ;
1267- let fn_sig = tcx. fn_sig ( similar_candidate. def_id ) . instantiate ( tcx, ty_args) ;
1268- let fn_sig =
1269- self . instantiate_binder_with_fresh_vars ( span, infer:: FnCall , fn_sig) ;
1270- if similar_candidate. fn_has_self_parameter {
1271- if let Some ( args) = args
1272- && fn_sig. inputs ( ) [ 1 ..] . len ( ) == args. len ( )
1273- {
1274- // We found a method with the same number of arguments as the method
1275- // call expression the user wrote.
1276- err. span_suggestion_verbose (
1277- span,
1278- format ! ( "there is {an} method with a similar name" ) ,
1279- similar_candidate. name ,
1280- Applicability :: MaybeIncorrect ,
1281- ) ;
1282- } else {
1283- // We found a method but either the expression is not a method call or
1284- // the argument count didn't match.
1285- err. span_help (
1286- tcx. def_span ( similar_candidate. def_id ) ,
1287- format ! (
1288- "there is {an} method `{}` with a similar name{}" ,
1289- similar_candidate. name,
1290- if let None = args {
1291- ""
1292- } else {
1293- ", but with different arguments"
1294- } ,
1295- ) ,
1296- ) ;
1297- }
1298- } else if let Some ( args) = args
1299- && fn_sig. inputs ( ) . len ( ) == args. len ( )
1300- {
1301- // We have fn call expression and the argument count match the associated
1302- // function we found.
1303- err. span_suggestion_verbose (
1304- span,
1305- format ! (
1306- "there is {an} {} with a similar name" ,
1307- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1308- ) ,
1309- similar_candidate. name ,
1310- Applicability :: MaybeIncorrect ,
1311- ) ;
1312- } else {
1313- err. span_help (
1314- tcx. def_span ( similar_candidate. def_id ) ,
1315- format ! (
1316- "there is {an} {} `{}` with a similar name" ,
1317- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1318- similar_candidate. name,
1319- ) ,
1320- ) ;
1321- }
1322- } else if let Mode :: Path = mode
1323- && args. unwrap_or ( & [ ] ) . is_empty ( )
1324- {
1325- // We have an associated item syntax and we found something that isn't an fn.
1326- err. span_suggestion_verbose (
1327- span,
1328- format ! (
1329- "there is {an} {} with a similar name" ,
1330- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1331- ) ,
1332- similar_candidate. name ,
1333- Applicability :: MaybeIncorrect ,
1334- ) ;
1335- } else {
1336- // The expression is a function or method call, but the item we found is an
1337- // associated const or type.
1338- err. span_help (
1339- tcx. def_span ( similar_candidate. def_id ) ,
1340- format ! (
1341- "there is {an} {} `{}` with a similar name" ,
1342- self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1343- similar_candidate. name,
1344- ) ,
1345- ) ;
1346- }
1259+ self . find_likely_intended_associated_item (
1260+ & mut err,
1261+ similar_candidate,
1262+ span,
1263+ args,
1264+ mode,
1265+ ) ;
13471266 }
13481267 }
13491268 // If an appropriate error source is not found, check method chain for possible candiates
@@ -1395,6 +1314,100 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13951314 Some ( err)
13961315 }
13971316
1317+ fn find_likely_intended_associated_item (
1318+ & self ,
1319+ err : & mut Diagnostic ,
1320+ similar_candidate : ty:: AssocItem ,
1321+ span : Span ,
1322+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
1323+ mode : Mode ,
1324+ ) {
1325+ let tcx = self . tcx ;
1326+ let def_kind = similar_candidate. kind . as_def_kind ( ) ;
1327+ let an = self . tcx . def_kind_descr_article ( def_kind, similar_candidate. def_id ) ;
1328+ // Methods are defined within the context of a struct and their first parameter
1329+ // is always `self`, which represents the instance of the struct the method is
1330+ // being called on Associated functions don’t take self as a parameter and they are
1331+ // not methods because they don’t have an instance of the struct to work with.
1332+ if def_kind == DefKind :: AssocFn {
1333+ let ty_args = self . infcx . fresh_args_for_item ( span, similar_candidate. def_id ) ;
1334+ let fn_sig = tcx. fn_sig ( similar_candidate. def_id ) . instantiate ( tcx, ty_args) ;
1335+ let fn_sig = self . instantiate_binder_with_fresh_vars ( span, infer:: FnCall , fn_sig) ;
1336+ if similar_candidate. fn_has_self_parameter {
1337+ if let Some ( args) = args
1338+ && fn_sig. inputs ( ) [ 1 ..] . len ( ) == args. len ( )
1339+ {
1340+ // We found a method with the same number of arguments as the method
1341+ // call expression the user wrote.
1342+ err. span_suggestion_verbose (
1343+ span,
1344+ format ! ( "there is {an} method with a similar name" ) ,
1345+ similar_candidate. name ,
1346+ Applicability :: MaybeIncorrect ,
1347+ ) ;
1348+ } else {
1349+ // We found a method but either the expression is not a method call or
1350+ // the argument count didn't match.
1351+ err. span_help (
1352+ tcx. def_span ( similar_candidate. def_id ) ,
1353+ format ! (
1354+ "there is {an} method `{}` with a similar name{}" ,
1355+ similar_candidate. name,
1356+ if let None = args { "" } else { ", but with different arguments" } ,
1357+ ) ,
1358+ ) ;
1359+ }
1360+ } else if let Some ( args) = args
1361+ && fn_sig. inputs ( ) . len ( ) == args. len ( )
1362+ {
1363+ // We have fn call expression and the argument count match the associated
1364+ // function we found.
1365+ err. span_suggestion_verbose (
1366+ span,
1367+ format ! (
1368+ "there is {an} {} with a similar name" ,
1369+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1370+ ) ,
1371+ similar_candidate. name ,
1372+ Applicability :: MaybeIncorrect ,
1373+ ) ;
1374+ } else {
1375+ err. span_help (
1376+ tcx. def_span ( similar_candidate. def_id ) ,
1377+ format ! (
1378+ "there is {an} {} `{}` with a similar name" ,
1379+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1380+ similar_candidate. name,
1381+ ) ,
1382+ ) ;
1383+ }
1384+ } else if let Mode :: Path = mode
1385+ && args. unwrap_or ( & [ ] ) . is_empty ( )
1386+ {
1387+ // We have an associated item syntax and we found something that isn't an fn.
1388+ err. span_suggestion_verbose (
1389+ span,
1390+ format ! (
1391+ "there is {an} {} with a similar name" ,
1392+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id)
1393+ ) ,
1394+ similar_candidate. name ,
1395+ Applicability :: MaybeIncorrect ,
1396+ ) ;
1397+ } else {
1398+ // The expression is a function or method call, but the item we found is an
1399+ // associated const or type.
1400+ err. span_help (
1401+ tcx. def_span ( similar_candidate. def_id ) ,
1402+ format ! (
1403+ "there is {an} {} `{}` with a similar name" ,
1404+ self . tcx. def_kind_descr( def_kind, similar_candidate. def_id) ,
1405+ similar_candidate. name,
1406+ ) ,
1407+ ) ;
1408+ }
1409+ }
1410+
13981411 pub ( crate ) fn confusable_method_name (
13991412 & self ,
14001413 err : & mut Diagnostic ,
0 commit comments