@@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
50
50
use std:: cmp:: { self , Ordering } ;
51
51
use std:: iter;
52
52
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
-
62
53
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
63
54
fn is_fn_ty ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
64
55
let tcx = self . tcx ;
@@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124
115
item_name : Ident ,
125
116
source : SelfSource < ' tcx > ,
126
117
error : MethodError < ' tcx > ,
127
- args : Option < MethodCallComponents < ' tcx > > ,
118
+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
128
119
expected : Expectation < ' tcx > ,
129
120
trait_missing_method : bool ,
130
121
) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
@@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
167
158
self . note_candidates_on_method_error (
168
159
rcvr_ty,
169
160
item_name,
161
+ source,
170
162
args,
171
163
span,
172
164
& mut err,
@@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
266
258
fn suggest_missing_writer (
267
259
& self ,
268
260
rcvr_ty : Ty < ' tcx > ,
269
- args : MethodCallComponents < ' tcx > ,
261
+ rcvr_expr : & hir :: Expr < ' tcx > ,
270
262
) -> DiagnosticBuilder < ' _ , ErrorGuaranteed > {
271
263
let ( ty_str, _ty_file) = self . tcx . short_ty_string ( rcvr_ty) ;
272
264
let mut err = struct_span_err ! (
273
265
self . tcx. sess,
274
- args . receiver . span,
266
+ rcvr_expr . span,
275
267
E0599 ,
276
268
"cannot write into `{}`" ,
277
269
ty_str
278
270
) ;
279
271
err. span_note (
280
- args . receiver . span ,
272
+ rcvr_expr . span ,
281
273
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method" ,
282
274
) ;
283
- if let ExprKind :: Lit ( _) = args . receiver . kind {
275
+ if let ExprKind :: Lit ( _) = rcvr_expr . kind {
284
276
err. span_help (
285
- args . receiver . span . shrink_to_lo ( ) ,
277
+ rcvr_expr . span . shrink_to_lo ( ) ,
286
278
"a writer is needed before this format string" ,
287
279
) ;
288
280
} ;
@@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296
288
rcvr_ty : Ty < ' tcx > ,
297
289
item_name : Ident ,
298
290
source : SelfSource < ' tcx > ,
299
- args : Option < MethodCallComponents < ' tcx > > ,
291
+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
300
292
sugg_span : Span ,
301
293
no_match_data : & mut NoMatchData < ' tcx > ,
302
294
expected : Expectation < ' tcx > ,
@@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
377
369
tcx. is_diagnostic_item ( sym:: write_macro, def_id)
378
370
|| tcx. is_diagnostic_item ( sym:: writeln_macro, def_id)
379
371
} ) && 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
+ } ;
397
391
if tcx. sess . source_map ( ) . is_multiline ( sugg_span) {
398
392
err. span_label ( sugg_span. with_hi ( span. lo ( ) ) , "" ) ;
399
393
}
@@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409
403
err. downgrade_to_delayed_bug ( ) ;
410
404
}
411
405
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
+
413
410
if tcx. ty_is_opaque_future ( rcvr_ty) && item_name. name == sym:: poll {
414
411
err. help ( format ! (
415
412
"method `poll` found on `Pin<&mut {ty_str}>`, \
@@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523
520
self . note_candidates_on_method_error (
524
521
rcvr_ty,
525
522
item_name,
523
+ source,
526
524
args,
527
525
span,
528
526
& mut err,
@@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
533
531
self . note_candidates_on_method_error (
534
532
rcvr_ty,
535
533
item_name,
534
+ source,
536
535
args,
537
536
span,
538
537
& mut err,
@@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
976
975
unsatisfied_bounds = true ;
977
976
}
978
977
} else if let ty:: Adt ( def, targs) = rcvr_ty. kind ( )
979
- && let Some ( args ) = args
978
+ && let SelfSource :: MethodCall ( rcvr_expr ) = source
980
979
{
981
980
// This is useful for methods on arbitrary self types that might have a simple
982
981
// mutability difference, like calling a method on `Pin<&mut Self>` that is on
@@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
999
998
rcvr_ty,
1000
999
& item_segment,
1001
1000
span,
1002
- args . full_expr ,
1003
- args . receiver ,
1001
+ tcx . hir ( ) . get_parent ( rcvr_expr . hir_id ) . expect_expr ( ) ,
1002
+ rcvr_expr ,
1004
1003
) {
1005
1004
err. span_note (
1006
1005
tcx. def_span ( method. def_id ) ,
@@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1169
1168
span,
1170
1169
rcvr_ty,
1171
1170
item_name,
1172
- args. map ( |MethodCallComponents { args, .. } | args. len ( ) + 1 ) ,
1171
+ args. map ( |args| args. len ( ) + 1 ) ,
1173
1172
source,
1174
1173
no_match_data. out_of_scope_traits . clone ( ) ,
1175
1174
& unsatisfied_predicates,
@@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1250
1249
& self ,
1251
1250
rcvr_ty : Ty < ' tcx > ,
1252
1251
item_name : Ident ,
1253
- args : Option < MethodCallComponents < ' tcx > > ,
1252
+ self_source : SelfSource < ' tcx > ,
1253
+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
1254
1254
span : Span ,
1255
1255
err : & mut Diagnostic ,
1256
1256
sources : & mut Vec < CandidateSource > ,
@@ -1339,6 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1339
1339
if let Some ( sugg) = print_disambiguation_help (
1340
1340
item_name,
1341
1341
args,
1342
+ self_source,
1342
1343
err,
1343
1344
path,
1344
1345
ty,
@@ -1378,6 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1378
1379
if let Some ( sugg) = print_disambiguation_help (
1379
1380
item_name,
1380
1381
args,
1382
+ self_source,
1381
1383
err,
1382
1384
path,
1383
1385
rcvr_ty,
@@ -1410,18 +1412,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1410
1412
1411
1413
/// Look at all the associated functions without receivers in the type's inherent impls
1412
1414
/// 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 > ) {
1414
1416
let ty:: Adt ( adt_def, _) = rcvr_ty. kind ( ) else {
1415
1417
return ;
1416
1418
} ;
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
- }
1425
1419
let mut items = self
1426
1420
. tcx
1427
1421
. inherent_impls ( adt_def. did ( ) )
@@ -1504,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1504
1498
rcvr_ty : Ty < ' tcx > ,
1505
1499
source : SelfSource < ' tcx > ,
1506
1500
item_name : Ident ,
1507
- args : Option < MethodCallComponents < ' tcx > > ,
1501
+ args : Option < & ' tcx [ hir :: Expr < ' tcx > ] > ,
1508
1502
sugg_span : Span ,
1509
1503
) {
1510
1504
let mut has_unsuggestable_args = false ;
@@ -1578,38 +1572,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1578
1572
None
1579
1573
} ;
1580
1574
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
+ )
1585
1605
} 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 ( )
1591
1608
} ;
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
- } ;
1613
1609
err. span_suggestion (
1614
1610
sugg_span,
1615
1611
"use associated function syntax instead" ,
@@ -3268,7 +3264,8 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
3268
3264
3269
3265
fn print_disambiguation_help < ' tcx > (
3270
3266
item_name : Ident ,
3271
- args : Option < MethodCallComponents < ' tcx > > ,
3267
+ args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
3268
+ source : SelfSource < ' tcx > ,
3272
3269
err : & mut Diagnostic ,
3273
3270
trait_name : String ,
3274
3271
rcvr_ty : Ty < ' _ > ,
@@ -3281,7 +3278,9 @@ fn print_disambiguation_help<'tcx>(
3281
3278
fn_has_self_parameter : bool ,
3282
3279
) -> Option < String > {
3283
3280
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
3285
3284
{
3286
3285
let args = format ! (
3287
3286
"({}{})" ,
0 commit comments