@@ -3761,17 +3761,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37613761 error_code : & str ,
37623762 c_variadic : bool ,
37633763 sugg_unit : bool | {
3764+ let ( span, start_span, args) = match & expr. kind {
3765+ hir:: ExprKind :: Call ( hir:: Expr { span, .. } , args) => ( * span, * span, & args[ ..] ) ,
3766+ hir:: ExprKind :: MethodCall ( path_segment, span, args) => (
3767+ * span,
3768+ // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
3769+ path_segment
3770+ . args
3771+ . and_then ( |args| args. args . iter ( ) . last ( ) )
3772+ // Account for `foo.bar::<T>()`.
3773+ . map ( |arg| {
3774+ // Skip the closing `>`.
3775+ tcx. sess
3776+ . source_map ( )
3777+ . next_point ( tcx. sess . source_map ( ) . next_point ( arg. span ( ) ) )
3778+ } )
3779+ . unwrap_or ( * span) ,
3780+ & args[ 1 ..] , // Skip the receiver.
3781+ ) ,
3782+ k => span_bug ! ( sp, "checking argument types on a non-call: `{:?}`" , k) ,
3783+ } ;
3784+ let arg_spans = if args. is_empty ( ) {
3785+ // foo()
3786+ // ^^^-- supplied 0 arguments
3787+ // |
3788+ // expected 2 arguments
3789+ vec ! [ tcx. sess. source_map( ) . next_point( start_span) . with_hi( sp. hi( ) ) ]
3790+ } else {
3791+ // foo(1, 2, 3)
3792+ // ^^^ - - - supplied 3 arguments
3793+ // |
3794+ // expected 2 arguments
3795+ args. iter ( ) . map ( |arg| arg. span ) . collect :: < Vec < Span > > ( )
3796+ } ;
3797+
37643798 let mut err = tcx. sess . struct_span_err_with_code (
3765- sp ,
3799+ span ,
37663800 & format ! (
37673801 "this function takes {}{} but {} {} supplied" ,
37683802 if c_variadic { "at least " } else { "" } ,
3769- potentially_plural_count( expected_count, "parameter " ) ,
3770- potentially_plural_count( arg_count, "parameter " ) ,
3803+ potentially_plural_count( expected_count, "argument " ) ,
3804+ potentially_plural_count( arg_count, "argument " ) ,
37713805 if arg_count == 1 { "was" } else { "were" }
37723806 ) ,
37733807 DiagnosticId :: Error ( error_code. to_owned ( ) ) ,
37743808 ) ;
3809+ let label = format ! ( "supplied {}" , potentially_plural_count( arg_count, "argument" ) ) ;
3810+ for ( i, span) in arg_spans. into_iter ( ) . enumerate ( ) {
3811+ err. span_label (
3812+ span,
3813+ if arg_count == 0 || i + 1 == arg_count { & label } else { "" } ,
3814+ ) ;
3815+ }
37753816
37763817 if let Some ( def_s) = def_span. map ( |sp| tcx. sess . source_map ( ) . def_span ( sp) ) {
37773818 err. span_label ( def_s, "defined here" ) ;
@@ -3788,11 +3829,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37883829 ) ;
37893830 } else {
37903831 err. span_label (
3791- sp ,
3832+ span ,
37923833 format ! (
37933834 "expected {}{}" ,
37943835 if c_variadic { "at least " } else { "" } ,
3795- potentially_plural_count( expected_count, "parameter " )
3836+ potentially_plural_count( expected_count, "argument " )
37963837 ) ,
37973838 ) ;
37983839 }
@@ -5494,8 +5535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54945535
54955536 self . tcx . sess . span_err (
54965537 span,
5497- "this function can only be invoked \
5498- directly, not through a function pointer",
5538+ "this function can only be invoked directly, not through a function pointer" ,
54995539 ) ;
55005540 }
55015541
0 commit comments