@@ -1230,6 +1230,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12301230 }
12311231 }
12321232
1233+ fn mk_obligation_for_def_id (
1234+ & self ,
1235+ def_id : DefId ,
1236+ output_ty : Ty < ' tcx > ,
1237+ cause : ObligationCause < ' tcx > ,
1238+ param_env : ty:: ParamEnv < ' tcx > ,
1239+ ) -> PredicateObligation < ' tcx > {
1240+ let new_trait_ref = ty:: TraitRef {
1241+ def_id,
1242+ substs : self . tcx . mk_substs_trait ( output_ty, & [ ] ) ,
1243+ } ;
1244+ Obligation :: new ( cause, param_env, new_trait_ref. to_predicate ( ) )
1245+ }
1246+
1247+
1248+ /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
1249+ /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
1250+ /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
12331251 fn suggest_fn_call (
12341252 & self ,
12351253 obligation : & PredicateObligation < ' tcx > ,
@@ -1248,19 +1266,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12481266 _ => return ,
12491267 } ;
12501268 let msg = format ! ( "use parentheses to call the {}" , callable) ;
1251- // We tried to apply the bound to an `fn` or closure. Check whether calling it would
1252- // evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
1253- // it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
12541269
1255- let new_trait_ref = ty:: TraitRef {
1256- def_id : trait_ref. def_id ( ) ,
1257- substs : self . tcx . mk_substs_trait ( output_ty. skip_binder ( ) , & [ ] ) ,
1258- } ;
1259- let obligation = Obligation :: new (
1270+ let obligation = self . mk_obligation_for_def_id (
1271+ trait_ref. def_id ( ) ,
1272+ output_ty. skip_binder ( ) ,
12601273 obligation. cause . clone ( ) ,
12611274 obligation. param_env ,
1262- new_trait_ref. to_predicate ( ) ,
12631275 ) ;
1276+
12641277 let get_name = |err : & mut DiagnosticBuilder < ' _ > , kind : & hir:: PatKind | -> Option < String > {
12651278 // Get the local name of this closure. This can be inaccurate because
12661279 // of the possibility of reassignment, but this should be good enough.
@@ -1277,73 +1290,72 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12771290 match self . evaluate_obligation ( & obligation) {
12781291 Ok ( EvaluationResult :: EvaluatedToOk ) |
12791292 Ok ( EvaluationResult :: EvaluatedToOkModuloRegions ) |
1280- Ok ( EvaluationResult :: EvaluatedToAmbig ) => {
1281- let hir = self . tcx . hir ( ) ;
1282- // Get the name of the callable and the arguments to be used in the suggestion.
1283- let snippet = match hir. get_if_local ( def_id) {
1284- Some ( hir:: Node :: Expr ( hir:: Expr {
1285- kind : hir:: ExprKind :: Closure ( _, decl, _, span, ..) ,
1286- ..
1287- } ) ) => {
1288- err. span_label ( * span, "consider calling this closure" ) ;
1289- let hir_id = match hir. as_local_hir_id ( def_id) {
1290- Some ( hir_id) => hir_id,
1291- None => return ,
1292- } ;
1293- let parent_node = hir. get_parent_node ( hir_id) ;
1294- let name = match hir. find ( parent_node) {
1295- Some ( hir:: Node :: Stmt ( hir:: Stmt {
1296- kind : hir:: StmtKind :: Local ( local) , ..
1297- } ) ) => match get_name ( err, & local. pat . kind ) {
1298- Some ( name) => name,
1299- None => return ,
1300- } ,
1301- // Different to previous arm because one is `&hir::Local` and the other
1302- // is `P<hir::Local>`.
1303- Some ( hir:: Node :: Local ( local) ) => match get_name ( err, & local. pat . kind ) {
1304- Some ( name) => name,
1305- None => return ,
1306- } ,
1307- _ => return ,
1308- } ;
1309- let args = decl. inputs . iter ( )
1310- . map ( |_| "_" )
1311- . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
1312- format ! ( "{}({})" , name, args)
1313- }
1314- Some ( hir:: Node :: Item ( hir:: Item {
1315- ident,
1316- kind : hir:: ItemKind :: Fn ( .., body_id) ,
1317- ..
1318- } ) ) => {
1319- err. span_label ( ident. span , "consider calling this function" ) ;
1320- let body = hir. body ( * body_id) ;
1321- let args = body. params . iter ( )
1322- . map ( |arg| match & arg. pat . kind {
1323- hir:: PatKind :: Binding ( _, _, ident, None )
1324- if ident. name != kw:: SelfLower => ident. to_string ( ) ,
1325- _ => "_" . to_string ( ) ,
1326- } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
1327- format ! ( "{}({})" , ident, args)
1328- }
1293+ Ok ( EvaluationResult :: EvaluatedToAmbig ) => { }
1294+ _ => return ,
1295+ }
1296+ let hir = self . tcx . hir ( ) ;
1297+ // Get the name of the callable and the arguments to be used in the suggestion.
1298+ let snippet = match hir. get_if_local ( def_id) {
1299+ Some ( hir:: Node :: Expr ( hir:: Expr {
1300+ kind : hir:: ExprKind :: Closure ( _, decl, _, span, ..) ,
1301+ ..
1302+ } ) ) => {
1303+ err. span_label ( * span, "consider calling this closure" ) ;
1304+ let hir_id = match hir. as_local_hir_id ( def_id) {
1305+ Some ( hir_id) => hir_id,
1306+ None => return ,
1307+ } ;
1308+ let parent_node = hir. get_parent_node ( hir_id) ;
1309+ let name = match hir. find ( parent_node) {
1310+ Some ( hir:: Node :: Stmt ( hir:: Stmt {
1311+ kind : hir:: StmtKind :: Local ( local) , ..
1312+ } ) ) => match get_name ( err, & local. pat . kind ) {
1313+ Some ( name) => name,
1314+ None => return ,
1315+ } ,
1316+ // Different to previous arm because one is `&hir::Local` and the other
1317+ // is `P<hir::Local>`.
1318+ Some ( hir:: Node :: Local ( local) ) => match get_name ( err, & local. pat . kind ) {
1319+ Some ( name) => name,
1320+ None => return ,
1321+ } ,
13291322 _ => return ,
13301323 } ;
1331- if points_at_arg {
1332- // When the obligation error has been ensured to have been caused by
1333- // an argument, the `obligation.cause.span` points at the expression
1334- // of the argument, so we can provide a suggestion. This is signaled
1335- // by `points_at_arg`. Otherwise, we give a more general note.
1336- err. span_suggestion (
1337- obligation. cause . span ,
1338- & msg,
1339- snippet,
1340- Applicability :: HasPlaceholders ,
1341- ) ;
1342- } else {
1343- err. help ( & format ! ( "{}: `{}`" , msg, snippet) ) ;
1344- }
1324+ let args = decl. inputs . iter ( )
1325+ . map ( |_| "_" )
1326+ . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
1327+ format ! ( "{}({})" , name, args)
1328+ }
1329+ Some ( hir:: Node :: Item ( hir:: Item {
1330+ ident,
1331+ kind : hir:: ItemKind :: Fn ( .., body_id) ,
1332+ ..
1333+ } ) ) => {
1334+ err. span_label ( ident. span , "consider calling this function" ) ;
1335+ let body = hir. body ( * body_id) ;
1336+ let args = body. params . iter ( )
1337+ . map ( |arg| match & arg. pat . kind {
1338+ hir:: PatKind :: Binding ( _, _, ident, None )
1339+ if ident. name != kw:: SelfLower => ident. to_string ( ) ,
1340+ _ => "_" . to_string ( ) ,
1341+ } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
1342+ format ! ( "{}({})" , ident, args)
13451343 }
1346- _ => { }
1344+ _ => return ,
1345+ } ;
1346+ if points_at_arg {
1347+ // When the obligation error has been ensured to have been caused by
1348+ // an argument, the `obligation.cause.span` points at the expression
1349+ // of the argument, so we can provide a suggestion. This is signaled
1350+ // by `points_at_arg`. Otherwise, we give a more general note.
1351+ err. span_suggestion (
1352+ obligation. cause . span ,
1353+ & msg,
1354+ snippet,
1355+ Applicability :: HasPlaceholders ,
1356+ ) ;
1357+ } else {
1358+ err. help ( & format ! ( "{}: `{}`" , msg, snippet) ) ;
13471359 }
13481360 }
13491361
@@ -1377,12 +1389,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13771389 if let ty:: Ref ( _, t_type, _) = trait_type. kind {
13781390 trait_type = t_type;
13791391
1380- let substs = self . tcx . mk_substs_trait ( trait_type , & [ ] ) ;
1381- let new_trait_ref = ty :: TraitRef :: new ( trait_ref. def_id , substs ) ;
1382- let new_obligation = Obligation :: new (
1392+ let new_obligation = self . mk_obligation_for_def_id (
1393+ trait_ref. def_id ,
1394+ trait_type ,
13831395 ObligationCause :: dummy ( ) ,
13841396 obligation. param_env ,
1385- new_trait_ref. to_predicate ( ) ,
13861397 ) ;
13871398
13881399 if self . predicate_may_hold ( & new_obligation) {
@@ -1440,12 +1451,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14401451 hir:: Mutability :: Immutable => self . tcx . mk_mut_ref ( region, t_type) ,
14411452 } ;
14421453
1443- let substs = self . tcx . mk_substs_trait ( & trait_type , & [ ] ) ;
1444- let new_trait_ref = ty :: TraitRef :: new ( trait_ref. skip_binder ( ) . def_id , substs ) ;
1445- let new_obligation = Obligation :: new (
1454+ let new_obligation = self . mk_obligation_for_def_id (
1455+ trait_ref. skip_binder ( ) . def_id ,
1456+ trait_type ,
14461457 ObligationCause :: dummy ( ) ,
14471458 obligation. param_env ,
1448- new_trait_ref. to_predicate ( ) ,
14491459 ) ;
14501460
14511461 if self . evaluate_obligation_no_overflow (
0 commit comments