1
Fork 0

Rollup merge of #75023 - euclio:argument-span, r=estebank

ensure arguments are included in count mismatch span

The current diagnostic isn't very helpful if the function header spans multiple lines. Lines comprising the function signature may be elided to keep the diagnostic short, but these lines are essential to fixing the error. This is made worse when the function has a body, because the last two lines of the span are then dedicated to showing the end of the body, which is irrelevant.

This PR changes the span to be a multispan made up of the header and the the arguments, ensuring they won't be elided. It also discards the function body from the span.

[Old](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f92d9f81a8c9416f0f04e4e09923b6d4):

```
error[E0061]: this function takes 6 arguments but 1 argument was supplied
  --> src/main.rs:18:5
   |
1  | / fn bar(
2  | |     a: i32,
3  | |     b: i32,
4  | |     c: i32,
...  |
14 | |     println!("{}", f);
15 | | }
   | |_- defined here
...
18 |       bar(1);
   |       ^^^ - supplied 1 argument
   |       |
   |       expected 6 arguments
```

New:

```
error[E0061]: this function takes 6 arguments but 1 argument was supplied
  --> $DIR/not-enough-arguments.rs:28:3
   |
LL |   bar(1);
   |   ^^^ - supplied 1 argument
   |   |
   |   expected 6 arguments
   |
note: function defined here
  --> $DIR/not-enough-arguments.rs:9:1
   |
LL | / fn bar(
LL | |     a: i32,
   | |     ^^^^^^^
LL | |     b: i32,
   | |     ^^^^^^^
LL | |     c: i32,
   | |     ^^^^^^^
LL | |     d: i32,
   | |     ^^^^^^^
LL | |     e: i32,
   | |     ^^^^^^^
LL | |     f: i32,
   | |     ^^^^^^^
LL | | ) {
   | |_^
```
This commit is contained in:
Dylan DPC 2020-10-16 02:09:58 +02:00 committed by GitHub
commit 075f2bfc39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 276 additions and 125 deletions

View file

@ -285,10 +285,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let (fn_sig, def_span) = match *callee_ty.kind() {
ty::FnDef(def_id, _) => {
(callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
}
let (fn_sig, def_id) = match *callee_ty.kind() {
ty::FnDef(def_id, _) => (callee_ty.fn_sig(self.tcx), Some(def_id)),
ty::FnPtr(sig) => (sig, None),
ref t => {
let mut unit_variant = None;
@ -427,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::DontTupleArguments,
def_span,
def_id,
);
fn_sig.output()

View file

@ -19,7 +19,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty};
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{self, Span};
use rustc_span::{self, MultiSpan, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode};
use std::mem::replace;
@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args_no_rcvr,
method.sig.c_variadic,
tuple_arguments,
self.tcx.hir().span_if_local(method.def_id),
Some(method.def_id),
);
method.sig.output()
}
@ -99,7 +99,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args: &'tcx [hir::Expr<'tcx>],
c_variadic: bool,
tuple_arguments: TupleArgumentsFlag,
def_span: Option<Span>,
def_id: Option<DefId>,
) {
let tcx = self.tcx;
// Grab the argument types, supplying fresh type variables
@ -172,9 +172,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) {
err.span_label(def_s, "defined here");
if let Some(def_id) = def_id {
if let Some(node) = tcx.hir().get_if_local(def_id) {
let mut spans: MultiSpan = node
.ident()
.map(|ident| ident.span)
.unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
.into();
if let Some(id) = node.body_id() {
let body = tcx.hir().body(id);
for param in body.params {
spans.push_span_label(param.span, String::new());
}
}
let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
}
if sugg_unit {
let sugg_span = tcx.sess.source_map().end_point(expr.span);
// remove closing `)` from the span