@@ -50,6 +50,15 @@ 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+
5362impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
5463 fn is_fn_ty ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
5564 let tcx = self . tcx ;
@@ -115,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
115124 item_name : Ident ,
116125 source : SelfSource < ' tcx > ,
117126 error : MethodError < ' tcx > ,
118- args : Option < ( & ' tcx hir :: Expr < ' tcx > , & ' tcx [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) > ,
127+ args : Option < MethodCallComponents < ' tcx > > ,
119128 expected : Expectation < ' tcx > ,
120129 trait_missing_method : bool ,
121130 ) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
@@ -257,18 +266,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
257266 fn suggest_missing_writer (
258267 & self ,
259268 rcvr_ty : Ty < ' tcx > ,
260- args : ( & ' tcx hir :: Expr < ' tcx > , & ' tcx [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) ,
269+ args : MethodCallComponents < ' tcx > ,
261270 ) -> DiagnosticBuilder < ' _ , ErrorGuaranteed > {
262271 let ( ty_str, _ty_file) = self . tcx . short_ty_string ( rcvr_ty) ;
263- let mut err =
264- struct_span_err ! ( self . tcx. sess, args. 0 . span, E0599 , "cannot write into `{}`" , ty_str) ;
272+ let mut err = struct_span_err ! (
273+ self . tcx. sess,
274+ args. receiver. span,
275+ E0599 ,
276+ "cannot write into `{}`" ,
277+ ty_str
278+ ) ;
265279 err. span_note (
266- args. 0 . span ,
280+ args. receiver . span ,
267281 "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method" ,
268282 ) ;
269- if let ExprKind :: Lit ( _) = args. 0 . kind {
283+ if let ExprKind :: Lit ( _) = args. receiver . kind {
270284 err. span_help (
271- args. 0 . span . shrink_to_lo ( ) ,
285+ args. receiver . span . shrink_to_lo ( ) ,
272286 "a writer is needed before this format string" ,
273287 ) ;
274288 } ;
@@ -282,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
282296 rcvr_ty : Ty < ' tcx > ,
283297 item_name : Ident ,
284298 source : SelfSource < ' tcx > ,
285- args : Option < ( & ' tcx hir :: Expr < ' tcx > , & ' tcx [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) > ,
299+ args : Option < MethodCallComponents < ' tcx > > ,
286300 sugg_span : Span ,
287301 no_match_data : & mut NoMatchData < ' tcx > ,
288302 expected : Expectation < ' tcx > ,
@@ -953,7 +967,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
953967
954968 unsatisfied_bounds = true ;
955969 }
956- } else if let ty:: Adt ( def, targs) = rcvr_ty. kind ( ) && let Some ( ( rcvr , _ , expr ) ) = args {
970+ } else if let ty:: Adt ( def, targs) = rcvr_ty. kind ( ) && let Some ( args ) = args {
957971 // This is useful for methods on arbitrary self types that might have a simple
958972 // mutability difference, like calling a method on `Pin<&mut Self>` that is on
959973 // `Pin<&Self>`.
@@ -972,7 +986,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
972986 } )
973987 ) ;
974988 let rcvr_ty = Ty :: new_adt ( tcx, * def, new_args) ;
975- if let Ok ( method) = self . lookup_method_for_diagnostic ( rcvr_ty, & item_segment, span, expr, rcvr) {
989+ if let Ok ( method) = self . lookup_method_for_diagnostic (
990+ rcvr_ty,
991+ & item_segment,
992+ span,
993+ args. full_expr ,
994+ args. receiver ,
995+ ) {
976996 err. span_note (
977997 tcx. def_span ( method. def_id ) ,
978998 format ! ( "{item_kind} is available for `{rcvr_ty}`" ) ,
@@ -1138,7 +1158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11381158 span,
11391159 rcvr_ty,
11401160 item_name,
1141- args. map ( |( _ , args, _ ) | args. len ( ) + 1 ) ,
1161+ args. map ( |MethodCallComponents { args, .. } | args. len ( ) + 1 ) ,
11421162 source,
11431163 no_match_data. out_of_scope_traits . clone ( ) ,
11441164 & unsatisfied_predicates,
@@ -1219,7 +1239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12191239 & self ,
12201240 rcvr_ty : Ty < ' tcx > ,
12211241 item_name : Ident ,
1222- args : Option < ( & ' tcx hir :: Expr < ' tcx > , & ' tcx [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) > ,
1242+ args : Option < MethodCallComponents < ' tcx > > ,
12231243 span : Span ,
12241244 err : & mut Diagnostic ,
12251245 sources : & mut Vec < CandidateSource > ,
@@ -1370,7 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13701390 rcvr_ty : Ty < ' tcx > ,
13711391 source : SelfSource < ' tcx > ,
13721392 item_name : Ident ,
1373- args : Option < ( & hir :: Expr < ' tcx > , & [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) > ,
1393+ args : Option < MethodCallComponents < ' tcx > > ,
13741394 sugg_span : Span ,
13751395 ) {
13761396 let mut has_unsuggestable_args = false ;
@@ -1442,7 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14421462 None
14431463 } ;
14441464 let mut applicability = Applicability :: MachineApplicable ;
1445- let args = if let Some ( ( receiver, args, _ ) ) = args {
1465+ let args = if let Some ( MethodCallComponents { receiver, args, .. } ) = args {
14461466 // The first arg is the same kind as the receiver
14471467 let explicit_args = if first_arg. is_some ( ) {
14481468 std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
@@ -3022,7 +3042,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
30223042
30233043fn print_disambiguation_help < ' tcx > (
30243044 item_name : Ident ,
3025- args : Option < ( & ' tcx hir :: Expr < ' tcx > , & ' tcx [ hir :: Expr < ' tcx > ] , & ' tcx hir :: Expr < ' tcx > ) > ,
3045+ args : Option < MethodCallComponents < ' tcx > > ,
30263046 err : & mut Diagnostic ,
30273047 trait_name : String ,
30283048 rcvr_ty : Ty < ' _ > ,
@@ -3034,7 +3054,11 @@ fn print_disambiguation_help<'tcx>(
30343054 fn_has_self_parameter : bool ,
30353055) {
30363056 let mut applicability = Applicability :: MachineApplicable ;
3037- let ( span, sugg) = if let ( ty:: AssocKind :: Fn , Some ( ( receiver, args, _) ) ) = ( kind, args) {
3057+ let ( span, sugg) = if let (
3058+ ty:: AssocKind :: Fn ,
3059+ Some ( MethodCallComponents { receiver, args, .. } ) ,
3060+ ) = ( kind, args)
3061+ {
30383062 let args = format ! (
30393063 "({}{})" ,
30403064 rcvr_ty. ref_mutability( ) . map_or( "" , |mutbl| mutbl. ref_prefix_str( ) ) ,
0 commit comments