@@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
5050use std:: cmp:: { self , Ordering } ;
5151use std:: iter;
5252
53- /// After identifying that `full_expr` is a method call, we use this type to keep the expression's
54- /// components readily available to us to point at the right place in diagnostics.
55- #[ derive( Debug , Clone , Copy ) ]
56- pub struct MethodCallComponents < ' tcx > {
57- pub receiver : & ' tcx hir:: Expr < ' tcx > ,
58- pub args : & ' tcx [ hir:: Expr < ' tcx > ] ,
59- pub full_expr : & ' tcx hir:: Expr < ' tcx > ,
60- }
61-
6253impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
6354 fn is_fn_ty ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
6455 let tcx = self . tcx ;
@@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124115 item_name : Ident ,
125116 source : SelfSource < ' tcx > ,
126117 error : MethodError < ' tcx > ,
127- args : Option < MethodCallComponents < ' tcx > > ,
118+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
128119 expected : Expectation < ' tcx > ,
129120 trait_missing_method : bool ,
130121 ) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
@@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
167158 self . note_candidates_on_method_error (
168159 rcvr_ty,
169160 item_name,
161+ source,
170162 args,
171163 span,
172164 & mut err,
@@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
266258 fn suggest_missing_writer (
267259 & self ,
268260 rcvr_ty : Ty < ' tcx > ,
269- args : MethodCallComponents < ' tcx > ,
261+ rcvr_expr : & hir :: Expr < ' tcx > ,
270262 ) -> DiagnosticBuilder < ' _ , ErrorGuaranteed > {
271263 let ( ty_str, _ty_file) = self . tcx . short_ty_string ( rcvr_ty) ;
272264 let mut err = struct_span_err ! (
273265 self . tcx. sess,
274- args . receiver . span,
266+ rcvr_expr . span,
275267 E0599 ,
276268 "cannot write into `{}`" ,
277269 ty_str
278270 ) ;
279271 err. span_note (
280- args . receiver . span ,
272+ rcvr_expr . span ,
281273 "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method" ,
282274 ) ;
283- if let ExprKind :: Lit ( _) = args . receiver . kind {
275+ if let ExprKind :: Lit ( _) = rcvr_expr . kind {
284276 err. span_help (
285- args . receiver . span . shrink_to_lo ( ) ,
277+ rcvr_expr . span . shrink_to_lo ( ) ,
286278 "a writer is needed before this format string" ,
287279 ) ;
288280 } ;
@@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296288 rcvr_ty : Ty < ' tcx > ,
297289 item_name : Ident ,
298290 source : SelfSource < ' tcx > ,
299- args : Option < MethodCallComponents < ' tcx > > ,
291+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
300292 sugg_span : Span ,
301293 no_match_data : & mut NoMatchData < ' tcx > ,
302294 expected : Expectation < ' tcx > ,
@@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
377369 tcx. is_diagnostic_item ( sym:: write_macro, def_id)
378370 || tcx. is_diagnostic_item ( sym:: writeln_macro, def_id)
379371 } ) && item_name. name == Symbol :: intern ( "write_fmt" ) ;
380- let mut err = if is_write && let Some ( args) = args {
381- self . suggest_missing_writer ( rcvr_ty, args)
382- } else {
383- tcx. sess . create_err ( NoAssociatedItem {
384- span,
385- item_kind,
386- item_name,
387- ty_prefix : if trait_missing_method {
388- // FIXME(mu001999) E0599 maybe not suitable here because it is for types
389- Cow :: from ( "trait" )
390- } else {
391- rcvr_ty. prefix_string ( self . tcx )
392- } ,
393- ty_str : ty_str_reported,
394- trait_missing_method,
395- } )
396- } ;
372+ let mut err =
373+ if is_write && let SelfSource :: MethodCall ( rcvr_expr) = source
374+ {
375+ self . suggest_missing_writer ( rcvr_ty, rcvr_expr)
376+ } else {
377+ tcx. sess . create_err ( NoAssociatedItem {
378+ span,
379+ item_kind,
380+ item_name,
381+ ty_prefix : if trait_missing_method {
382+ // FIXME(mu001999) E0599 maybe not suitable here because it is for types
383+ Cow :: from ( "trait" )
384+ } else {
385+ rcvr_ty. prefix_string ( self . tcx )
386+ } ,
387+ ty_str : ty_str_reported,
388+ trait_missing_method,
389+ } )
390+ } ;
397391 if tcx. sess . source_map ( ) . is_multiline ( sugg_span) {
398392 err. span_label ( sugg_span. with_hi ( span. lo ( ) ) , "" ) ;
399393 }
@@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409403 err. downgrade_to_delayed_bug ( ) ;
410404 }
411405
412- self . find_builder_fn ( & mut err, rcvr_ty, source) ;
406+ if matches ! ( source, SelfSource :: QPath ( _) ) && args. is_some ( ) {
407+ self . find_builder_fn ( & mut err, rcvr_ty) ;
408+ }
409+
413410 if tcx. ty_is_opaque_future ( rcvr_ty) && item_name. name == sym:: poll {
414411 err. help ( format ! (
415412 "method `poll` found on `Pin<&mut {ty_str}>`, \
@@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523520 self . note_candidates_on_method_error (
524521 rcvr_ty,
525522 item_name,
523+ source,
526524 args,
527525 span,
528526 & mut err,
@@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
533531 self . note_candidates_on_method_error (
534532 rcvr_ty,
535533 item_name,
534+ source,
536535 args,
537536 span,
538537 & mut err,
@@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
976975 unsatisfied_bounds = true ;
977976 }
978977 } else if let ty:: Adt ( def, targs) = rcvr_ty. kind ( )
979- && let Some ( args ) = args
978+ && let SelfSource :: MethodCall ( rcvr_expr ) = source
980979 {
981980 // This is useful for methods on arbitrary self types that might have a simple
982981 // mutability difference, like calling a method on `Pin<&mut Self>` that is on
@@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
999998 rcvr_ty,
1000999 & item_segment,
10011000 span,
1002- args . full_expr ,
1003- args . receiver ,
1001+ tcx . hir ( ) . get_parent ( rcvr_expr . hir_id ) . expect_expr ( ) ,
1002+ rcvr_expr ,
10041003 ) {
10051004 err. span_note (
10061005 tcx. def_span ( method. def_id ) ,
@@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11691168 span,
11701169 rcvr_ty,
11711170 item_name,
1172- args. map ( |MethodCallComponents { args, .. } | args. len ( ) + 1 ) ,
1171+ args. map ( |args| args. len ( ) + 1 ) ,
11731172 source,
11741173 no_match_data. out_of_scope_traits . clone ( ) ,
11751174 & unsatisfied_predicates,
@@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12501249 & self ,
12511250 rcvr_ty : Ty < ' tcx > ,
12521251 item_name : Ident ,
1253- args : Option < MethodCallComponents < ' tcx > > ,
1252+ self_source : SelfSource < ' tcx > ,
1253+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
12541254 span : Span ,
12551255 err : & mut Diagnostic ,
12561256 sources : & mut Vec < CandidateSource > ,
@@ -1339,6 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13391339 if let Some ( sugg) = print_disambiguation_help (
13401340 item_name,
13411341 args,
1342+ self_source,
13421343 err,
13431344 path,
13441345 ty,
@@ -1378,6 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13781379 if let Some ( sugg) = print_disambiguation_help (
13791380 item_name,
13801381 args,
1382+ self_source,
13811383 err,
13821384 path,
13831385 rcvr_ty,
@@ -1410,18 +1412,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14101412
14111413 /// Look at all the associated functions without receivers in the type's inherent impls
14121414 /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
1413- fn find_builder_fn ( & self , err : & mut Diagnostic , rcvr_ty : Ty < ' tcx > , source : SelfSource < ' tcx > ) {
1415+ fn find_builder_fn ( & self , err : & mut Diagnostic , rcvr_ty : Ty < ' tcx > ) {
14141416 let ty:: Adt ( adt_def, _) = rcvr_ty. kind ( ) else {
14151417 return ;
14161418 } ;
1417- let SelfSource :: QPath ( ty) = source else {
1418- return ;
1419- } ;
1420- let hir = self . tcx . hir ( ) ;
1421- if let Some ( Node :: Pat ( _) ) = hir. find ( hir. parent_id ( ty. hir_id ) ) {
1422- // Do not suggest a fn call when a pattern is expected.
1423- return ;
1424- }
14251419 let mut items = self
14261420 . tcx
14271421 . inherent_impls ( adt_def. did ( ) )
@@ -1504,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15041498 rcvr_ty : Ty < ' tcx > ,
15051499 source : SelfSource < ' tcx > ,
15061500 item_name : Ident ,
1507- args : Option < MethodCallComponents < ' tcx > > ,
1501+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
15081502 sugg_span : Span ,
15091503 ) {
15101504 let mut has_unsuggestable_args = false ;
@@ -1578,38 +1572,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15781572 None
15791573 } ;
15801574 let mut applicability = Applicability :: MachineApplicable ;
1581- let args = if let Some ( MethodCallComponents { receiver, args, .. } ) = args {
1582- // The first arg is the same kind as the receiver
1583- let explicit_args = if first_arg. is_some ( ) {
1584- std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
1575+ let args = if let SelfSource :: MethodCall ( receiver) = source
1576+ && let Some ( args) = args
1577+ {
1578+ // The first arg is the same kind as the receiver
1579+ let explicit_args = if first_arg. is_some ( ) {
1580+ std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
1581+ } else {
1582+ // There is no `Self` kind to infer the arguments from
1583+ if has_unsuggestable_args {
1584+ applicability = Applicability :: HasPlaceholders ;
1585+ }
1586+ args. iter ( ) . collect ( )
1587+ } ;
1588+ format ! (
1589+ "({}{})" ,
1590+ first_arg. unwrap_or( "" ) ,
1591+ explicit_args
1592+ . iter( )
1593+ . map( |arg| self
1594+ . tcx
1595+ . sess
1596+ . source_map( )
1597+ . span_to_snippet( arg. span)
1598+ . unwrap_or_else( |_| {
1599+ applicability = Applicability :: HasPlaceholders ;
1600+ "_" . to_owned( )
1601+ } ) )
1602+ . collect:: <Vec <_>>( )
1603+ . join( ", " ) ,
1604+ )
15851605 } else {
1586- // There is no `Self` kind to infer the arguments from
1587- if has_unsuggestable_args {
1588- applicability = Applicability :: HasPlaceholders ;
1589- }
1590- args. iter ( ) . collect ( )
1606+ applicability = Applicability :: HasPlaceholders ;
1607+ "(...)" . to_owned ( )
15911608 } ;
1592- format ! (
1593- "({}{})" ,
1594- first_arg. unwrap_or( "" ) ,
1595- explicit_args
1596- . iter( )
1597- . map( |arg| self
1598- . tcx
1599- . sess
1600- . source_map( )
1601- . span_to_snippet( arg. span)
1602- . unwrap_or_else( |_| {
1603- applicability = Applicability :: HasPlaceholders ;
1604- "_" . to_owned( )
1605- } ) )
1606- . collect:: <Vec <_>>( )
1607- . join( ", " ) ,
1608- )
1609- } else {
1610- applicability = Applicability :: HasPlaceholders ;
1611- "(...)" . to_owned ( )
1612- } ;
16131609 err. span_suggestion (
16141610 sugg_span,
16151611 "use associated function syntax instead" ,
@@ -3268,7 +3264,8 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
32683264
32693265fn print_disambiguation_help < ' tcx > (
32703266 item_name : Ident ,
3271- args : Option < MethodCallComponents < ' tcx > > ,
3267+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
3268+ source : SelfSource < ' tcx > ,
32723269 err : & mut Diagnostic ,
32733270 trait_name : String ,
32743271 rcvr_ty : Ty < ' _ > ,
@@ -3281,7 +3278,9 @@ fn print_disambiguation_help<'tcx>(
32813278 fn_has_self_parameter : bool ,
32823279) -> Option < String > {
32833280 Some (
3284- if let ( ty:: AssocKind :: Fn , Some ( MethodCallComponents { receiver, args, .. } ) ) = ( kind, args)
3281+ if matches ! ( kind, ty:: AssocKind :: Fn )
3282+ && let SelfSource :: MethodCall ( receiver) = source
3283+ && let Some ( args) = args
32853284 {
32863285 let args = format ! (
32873286 "({}{})" ,
0 commit comments