diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2141d5b1ee7..52727e3a619 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2742,4 +2742,32 @@ impl<'hir> Node<'hir> { _ => None, } } + + pub fn hir_id(&self) -> Option { + match self { + Node::Item(Item { hir_id, .. }) + | Node::ForeignItem(ForeignItem { hir_id, .. }) + | Node::TraitItem(TraitItem { hir_id, .. }) + | Node::ImplItem(ImplItem { hir_id, .. }) + | Node::Field(StructField { hir_id, .. }) + | Node::AnonConst(AnonConst { hir_id, .. }) + | Node::Expr(Expr { hir_id, .. }) + | Node::Stmt(Stmt { hir_id, .. }) + | Node::Ty(Ty { hir_id, .. }) + | Node::Binding(Pat { hir_id, .. }) + | Node::Pat(Pat { hir_id, .. }) + | Node::Arm(Arm { hir_id, .. }) + | Node::Block(Block { hir_id, .. }) + | Node::Local(Local { hir_id, .. }) + | Node::MacroDef(MacroDef { hir_id, .. }) + | Node::Lifetime(Lifetime { hir_id, .. }) + | Node::Param(Param { hir_id, .. }) + | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), + Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), + Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, + Node::Variant(Variant { id, .. }) => Some(*id), + Node::Ctor(variant) => variant.ctor_hir_id(), + Node::Crate(_) | Node::Visibility(_) => None, + } + } } diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 740783aeb9d..a38fb9642b9 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -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() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 3224e04ee49..fd2f5eb5018 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -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, + def_id: Option, ) { 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 diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr index 7bc06134a69..d0577e4864a 100644 --- a/src/test/ui/arg-count-mismatch.stderr +++ b/src/test/ui/arg-count-mismatch.stderr @@ -1,13 +1,16 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/arg-count-mismatch.rs:5:28 | -LL | fn f(x: isize) { } - | -------------- defined here -LL | LL | fn main() { let i: (); i = f(); } | ^-- supplied 0 arguments | | | expected 1 argument + | +note: function defined here + --> $DIR/arg-count-mismatch.rs:3:4 + | +LL | fn f(x: isize) { } + | ^ -------- error: aborting due to previous error diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 89ea65fd43f..6f2a6c359b5 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -7,24 +7,30 @@ LL | fn printf(_: *const u8, ...); error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied --> $DIR/variadic-ffi-1.rs:17:9 | -LL | fn foo(f: isize, x: u8, ...); - | ----------------------------- defined here -... LL | foo(); | ^^^-- supplied 0 arguments | | | expected at least 2 arguments + | +note: function defined here + --> $DIR/variadic-ffi-1.rs:10:8 + | +LL | fn foo(f: isize, x: u8, ...); + | ^^^ error[E0060]: this function takes at least 2 arguments but 1 argument was supplied --> $DIR/variadic-ffi-1.rs:18:9 | -LL | fn foo(f: isize, x: u8, ...); - | ----------------------------- defined here -... LL | foo(1); | ^^^ - supplied 1 argument | | | expected at least 2 arguments + | +note: function defined here + --> $DIR/variadic-ffi-1.rs:10:8 + | +LL | fn foo(f: isize, x: u8, ...); + | ^^^ error[E0308]: mismatched types --> $DIR/variadic-ffi-1.rs:20:56 diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr index a600592c6c2..c80014d1476 100644 --- a/src/test/ui/error-codes/E0060.stderr +++ b/src/test/ui/error-codes/E0060.stderr @@ -1,13 +1,16 @@ error[E0060]: this function takes at least 1 argument but 0 arguments were supplied --> $DIR/E0060.rs:6:14 | -LL | fn printf(_: *const u8, ...) -> u32; - | ------------------------------------ defined here -... LL | unsafe { printf(); } | ^^^^^^-- supplied 0 arguments | | | expected at least 1 argument + | +note: function defined here + --> $DIR/E0060.rs:2:8 + | +LL | fn printf(_: *const u8, ...) -> u32; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr index dfefa0df313..98488a2d298 100644 --- a/src/test/ui/error-codes/E0061.stderr +++ b/src/test/ui/error-codes/E0061.stderr @@ -1,24 +1,30 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/E0061.rs:6:5 | -LL | fn f(a: u16, b: &str) {} - | --------------------- defined here -... LL | f(0); | ^ - supplied 1 argument | | | expected 2 arguments + | +note: function defined here + --> $DIR/E0061.rs:1:4 + | +LL | fn f(a: u16, b: &str) {} + | ^ ------ ------- error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/E0061.rs:10:5 | -LL | fn f2(a: u16) {} - | ------------- defined here -... LL | f2(); | ^^-- supplied 0 arguments | | | expected 1 argument + | +note: function defined here + --> $DIR/E0061.rs:3:4 + | +LL | fn f2(a: u16) {} + | ^^ ------ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr index bd08fc1bfae..2cc1c7a2e72 100644 --- a/src/test/ui/hrtb/issue-58451.stderr +++ b/src/test/ui/hrtb/issue-58451.stderr @@ -1,16 +1,16 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/issue-58451.rs:12:9 | -LL | / fn f(i: I) -LL | | where -LL | | I: IntoIterator, -LL | | I::Item: for<'a> Into<&'a ()>, - | |__________________________________- defined here -... -LL | f(&[f()]); - | ^-- supplied 0 arguments - | | - | expected 1 argument +LL | f(&[f()]); + | ^-- supplied 0 arguments + | | + | expected 1 argument + | +note: function defined here + --> $DIR/issue-58451.rs:5:4 + | +LL | fn f(i: I) + | ^ ---- error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr index a952c9b46c9..b10d26abe34 100644 --- a/src/test/ui/issues/issue-18819.stderr +++ b/src/test/ui/issues/issue-18819.stderr @@ -1,13 +1,16 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/issue-18819.rs:16:5 | -LL | fn print_x(_: &dyn Foo, extra: &str) { - | ----------------------------------------------- defined here -... LL | print_x(X); | ^^^^^^^ - supplied 1 argument | | | expected 2 arguments + | +note: function defined here + --> $DIR/issue-18819.rs:11:4 + | +LL | fn print_x(_: &dyn Foo, extra: &str) { + | ^^^^^^^ ---------------------- ----------- error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26094.stderr b/src/test/ui/issues/issue-26094.stderr index 2038d88bf46..a6f1ac9286c 100644 --- a/src/test/ui/issues/issue-26094.stderr +++ b/src/test/ui/issues/issue-26094.stderr @@ -4,11 +4,14 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied LL | $other(None) | ---- supplied 1 argument ... -LL | fn some_function() {} - | ------------------ defined here -... LL | some_macro!(some_function); | ^^^^^^^^^^^^^ expected 0 arguments + | +note: function defined here + --> $DIR/issue-26094.rs:7:4 + | +LL | fn some_function() {} + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4935.stderr b/src/test/ui/issues/issue-4935.stderr index 0cc686e1cf8..03b9b91edef 100644 --- a/src/test/ui/issues/issue-4935.stderr +++ b/src/test/ui/issues/issue-4935.stderr @@ -1,13 +1,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/issue-4935.rs:5:13 | -LL | fn foo(a: usize) {} - | ---------------- defined here -LL | LL | fn main() { foo(5, 6) } | ^^^ - - supplied 2 arguments | | | expected 1 argument + | +note: function defined here + --> $DIR/issue-4935.rs:3:4 + | +LL | fn foo(a: usize) {} + | ^^^ -------- error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b0d1bb9823b..60f9eeeca27 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -1,35 +1,44 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/method-call-err-msg.rs:13:7 | -LL | fn zero(self) -> Foo { self } - | -------------------- defined here -... LL | x.zero(0) | ^^^^ - supplied 1 argument | | | expected 0 arguments + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:5:8 + | +LL | fn zero(self) -> Foo { self } + | ^^^^ ---- error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:14:7 | -LL | fn one(self, _: isize) -> Foo { self } - | ----------------------------- defined here -... LL | .one() | ^^^- supplied 0 arguments | | | expected 1 argument + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:6:8 + | +LL | fn one(self, _: isize) -> Foo { self } + | ^^^ ---- -------- error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/method-call-err-msg.rs:15:7 | -LL | fn two(self, _: isize, _: isize) -> Foo { self } - | --------------------------------------- defined here -... LL | .two(0); | ^^^ - supplied 1 argument | | | expected 2 arguments + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:7:8 + | +LL | fn two(self, _: isize, _: isize) -> Foo { self } + | ^^^ ---- -------- -------- error[E0599]: no method named `take` found for struct `Foo` in the current scope --> $DIR/method-call-err-msg.rs:19:7 @@ -53,13 +62,16 @@ LL | .take() error[E0061]: this function takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 | -LL | fn three(self, _: T, _: T, _: T) -> Foo { self } - | ------------------------------------------ defined here -... LL | y.three::(); | ^^^^^--------- supplied 0 arguments | | | expected 3 arguments + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:8:8 + | +LL | fn three(self, _: T, _: T, _: T) -> Foo { self } + | ^^^^^ ---- ---- ---- ---- error: aborting due to 5 previous errors diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs index 631bb1dd274..42476255188 100644 --- a/src/test/ui/not-enough-arguments.rs +++ b/src/test/ui/not-enough-arguments.rs @@ -6,7 +6,26 @@ fn foo(a: isize, b: isize, c: isize, d:isize) { panic!(); } +// Check that all arguments are shown in the error message, even if they're across multiple lines. +fn bar( + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, +) { + println!("{}", a); + println!("{}", b); + println!("{}", c); + println!("{}", d); + println!("{}", e); + println!("{}", f); +} + fn main() { foo(1, 2, 3); //~^ ERROR this function takes 4 arguments but 3 + bar(1, 2, 3); + //~^ ERROR this function takes 6 arguments but 3 } diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr index f2b57f71400..df957837241 100644 --- a/src/test/ui/not-enough-arguments.stderr +++ b/src/test/ui/not-enough-arguments.stderr @@ -1,14 +1,43 @@ error[E0061]: this function takes 4 arguments but 3 arguments were supplied - --> $DIR/not-enough-arguments.rs:10:3 + --> $DIR/not-enough-arguments.rs:27:3 | -LL | fn foo(a: isize, b: isize, c: isize, d:isize) { - | --------------------------------------------- defined here -... LL | foo(1, 2, 3); | ^^^ - - - supplied 3 arguments | | | expected 4 arguments + | +note: function defined here + --> $DIR/not-enough-arguments.rs:5:4 + | +LL | fn foo(a: isize, b: isize, c: isize, d:isize) { + | ^^^ -------- -------- -------- ------- -error: aborting due to previous error +error[E0061]: this function takes 6 arguments but 3 arguments were supplied + --> $DIR/not-enough-arguments.rs:29:3 + | +LL | bar(1, 2, 3); + | ^^^ - - - supplied 3 arguments + | | + | expected 6 arguments + | +note: function defined here + --> $DIR/not-enough-arguments.rs:10:4 + | +LL | fn bar( + | ^^^ +LL | a: i32, + | ------ +LL | b: i32, + | ------ +LL | c: i32, + | ------ +LL | d: i32, + | ------ +LL | e: i32, + | ------ +LL | f: i32, + | ------ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 40c3219bf27..5cda17fd6a1 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -53,13 +53,16 @@ LL | fn bar(_: x, y: usize) {} error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:7:5 | -LL | fn foo(Option, String) {} - | --------------------------- defined here -... LL | foo(Some(42), 2, ""); | ^^^ -------- - -- supplied 3 arguments | | | expected 2 arguments + | +note: function defined here + --> $DIR/issue-34264.rs:1:4 + | +LL | fn foo(Option, String) {} + | ^^^ ----------- ------ error[E0308]: mismatched types --> $DIR/issue-34264.rs:8:13 @@ -70,13 +73,16 @@ LL | bar("", ""); error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:10:5 | -LL | fn bar(x, y: usize) {} - | ------------------- defined here -... LL | bar(1, 2, 3); | ^^^ - - - supplied 3 arguments | | | expected 2 arguments + | +note: function defined here + --> $DIR/issue-34264.rs:3:4 + | +LL | fn bar(x, y: usize) {} + | ^^^ - -------- error: aborting due to 6 previous errors diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index f6344fba3d3..b15da2cb479 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -12,34 +12,42 @@ LL | let _: Result<(), String> = Ok(()); error[E0061]: this function takes 2 arguments but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:12:5 | -LL | fn foo(():(), ():()) {} - | -------------------- defined here -... LL | foo(); | ^^^-- supplied 0 arguments | | | expected 2 arguments + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/missing-unit-argument.rs:13:5 | -LL | fn foo(():(), ():()) {} - | -------------------- defined here -... LL | foo(()); | ^^^ -- supplied 1 argument | | | expected 2 arguments + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:14:5 | -LL | fn bar(():()) {} - | ------------- defined here -... LL | bar(); | ^^^-- supplied 0 arguments | +note: function defined here + --> $DIR/missing-unit-argument.rs:2:4 + | +LL | fn bar(():()) {} + | ^^^ ----- help: expected the unit value `()`; create it with empty parentheses | LL | bar(()); @@ -48,12 +56,14 @@ LL | bar(()); error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:15:7 | -LL | fn baz(self, (): ()) { } - | -------------------- defined here -... LL | S.baz(); | ^^^- supplied 0 arguments | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:6:8 + | +LL | fn baz(self, (): ()) { } + | ^^^ ---- ------ help: expected the unit value `()`; create it with empty parentheses | LL | S.baz(()); @@ -62,12 +72,14 @@ LL | S.baz(()); error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:16:7 | -LL | fn generic(self, _: T) { } - | ------------------------- defined here -... LL | S.generic::<()>(); | ^^^^^^^------ supplied 0 arguments | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:7:8 + | +LL | fn generic(self, _: T) { } + | ^^^^^^^ ---- ---- help: expected the unit value `()`; create it with empty parentheses | LL | S.generic::<()>(()); diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr index 46e7dd0c517..20e26058451 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr @@ -1,13 +1,16 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5 | -LL | V(u8) - | ----- defined here -... LL | ::V(); | ^^^^^^-- supplied 0 arguments | | | expected 1 argument + | +note: tuple variant defined here + --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5 + | +LL | V(u8) + | ^^^^^ error[E0308]: mismatched types --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17