Skip to content

Commit 1549576

Browse files
committed
Point at closure args too
1 parent 7bf47bf commit 1549576

File tree

7 files changed

+97
-81
lines changed

7 files changed

+97
-81
lines changed

Diff for: compiler/rustc_typeck/src/check/callee.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn check_legal_trait_for_method_call(
5959

6060
enum CallStep<'tcx> {
6161
Builtin(Ty<'tcx>),
62-
DeferredClosure(ty::FnSig<'tcx>),
62+
DeferredClosure(DefId, ty::FnSig<'tcx>),
6363
/// E.g., enum variant constructors.
6464
Overloaded(MethodCallee<'tcx>),
6565
}
@@ -107,8 +107,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
107107
self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
108108
}
109109

110-
Some(CallStep::DeferredClosure(fn_sig)) => {
111-
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
110+
Some(CallStep::DeferredClosure(def_id, fn_sig)) => {
111+
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig)
112112
}
113113

114114
Some(CallStep::Overloaded(method_callee)) => {
@@ -171,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
171171
closure_substs: substs,
172172
},
173173
);
174-
return Some(CallStep::DeferredClosure(closure_sig));
174+
return Some(CallStep::DeferredClosure(def_id, closure_sig));
175175
}
176176
}
177177

@@ -533,6 +533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
533533
call_expr: &'tcx hir::Expr<'tcx>,
534534
arg_exprs: &'tcx [hir::Expr<'tcx>],
535535
expected: Expectation<'tcx>,
536+
closure_def_id: DefId,
536537
fn_sig: ty::FnSig<'tcx>,
537538
) -> Ty<'tcx> {
538539
// `fn_sig` is the *signature* of the closure being called. We
@@ -555,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
555556
arg_exprs,
556557
fn_sig.c_variadic,
557558
TupleArgumentsFlag::TupleArguments,
558-
None,
559+
Some(closure_def_id),
559560
);
560561

561562
fn_sig.output()

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+49-73
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_infer::infer::TypeTrace;
2424
use rustc_middle::ty::adjustment::AllowTwoPhase;
2525
use rustc_middle::ty::error::TypeError;
2626
use rustc_middle::ty::fold::TypeFoldable;
27-
use rustc_middle::ty::{self, Ty};
27+
use rustc_middle::ty::{self, Ty, TyCtxt};
2828
use rustc_session::Session;
2929
use rustc_span::symbol::Ident;
3030
use rustc_span::{self, Span};
@@ -523,24 +523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523523
format!("arguments to this {} are incorrect", call_name),
524524
);
525525
// Call out where the function is defined
526-
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
527-
let mut spans: MultiSpan = def_span.into();
528-
529-
let params = tcx
530-
.hir()
531-
.get_if_local(def_id)
532-
.and_then(|node| node.body_id())
533-
.into_iter()
534-
.map(|id| tcx.hir().body(id).params)
535-
.flatten();
536-
537-
for param in params {
538-
spans.push_span_label(param.span, String::new());
539-
}
540-
541-
let def_kind = tcx.def_kind(def_id);
542-
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
543-
}
526+
label_fn_like(tcx, &mut err, fn_def_id);
544527
err.emit();
545528
break 'errors;
546529
}
@@ -558,24 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
558541
DiagnosticId::Error(err_code.to_owned()),
559542
);
560543
// Call out where the function is defined
561-
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
562-
let mut spans: MultiSpan = def_span.into();
563-
564-
let params = tcx
565-
.hir()
566-
.get_if_local(def_id)
567-
.and_then(|node| node.body_id())
568-
.into_iter()
569-
.map(|id| tcx.hir().body(id).params)
570-
.flatten();
571-
572-
for param in params {
573-
spans.push_span_label(param.span, String::new());
574-
}
575-
576-
let def_kind = tcx.def_kind(def_id);
577-
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
578-
}
544+
label_fn_like(tcx, &mut err, fn_def_id);
579545
err.multipart_suggestion(
580546
"use parentheses to construct a tuple",
581547
vec![(start, '('.to_string()), (end, ')'.to_string())],
@@ -613,24 +579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
613579
format!("arguments to this {} are incorrect", call_name),
614580
);
615581
// Call out where the function is defined
616-
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
617-
let mut spans: MultiSpan = def_span.into();
618-
619-
let params = tcx
620-
.hir()
621-
.get_if_local(def_id)
622-
.and_then(|node| node.body_id())
623-
.into_iter()
624-
.map(|id| tcx.hir().body(id).params)
625-
.flatten();
626-
627-
for param in params {
628-
spans.push_span_label(param.span, String::new());
629-
}
630-
631-
let def_kind = tcx.def_kind(def_id);
632-
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
633-
}
582+
label_fn_like(tcx, &mut err, fn_def_id);
634583
err.emit();
635584
break 'errors;
636585
}
@@ -948,24 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
948897
}
949898

950899
// Call out where the function is defined
951-
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
952-
let mut spans: MultiSpan = def_span.into();
953-
954-
let params = tcx
955-
.hir()
956-
.get_if_local(def_id)
957-
.and_then(|node| node.body_id())
958-
.into_iter()
959-
.flat_map(|id| tcx.hir().body(id).params)
960-
;
961-
962-
for param in params {
963-
spans.push_span_label(param.span, String::new());
964-
}
965-
966-
let def_kind = tcx.def_kind(def_id);
967-
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
968-
}
900+
label_fn_like(tcx, &mut err, fn_def_id);
969901

970902
// And add a suggestion block for all of the parameters
971903
let suggestion_text = match suggestion_text {
@@ -1790,3 +1722,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17901722
}
17911723
}
17921724
}
1725+
1726+
fn label_fn_like<'tcx>(
1727+
tcx: TyCtxt<'tcx>,
1728+
err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
1729+
def_id: Option<DefId>,
1730+
) {
1731+
let Some(def_id) = def_id else {
1732+
return;
1733+
};
1734+
1735+
if let Some(def_span) = tcx.def_ident_span(def_id) {
1736+
let mut spans: MultiSpan = def_span.into();
1737+
1738+
let params = tcx
1739+
.hir()
1740+
.get_if_local(def_id)
1741+
.and_then(|node| node.body_id())
1742+
.into_iter()
1743+
.map(|id| tcx.hir().body(id).params)
1744+
.flatten();
1745+
1746+
for param in params {
1747+
spans.push_span_label(param.span, String::new());
1748+
}
1749+
1750+
let def_kind = tcx.def_kind(def_id);
1751+
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1752+
} else {
1753+
match tcx.hir().get_if_local(def_id) {
1754+
Some(hir::Node::Expr(hir::Expr {
1755+
kind: hir::ExprKind::Closure(_, _, _, span, ..),
1756+
..
1757+
})) => {
1758+
let spans: MultiSpan = (*span).into();
1759+
1760+
// Note: We don't point to param spans here because they overlap
1761+
// with the closure span itself
1762+
1763+
err.span_note(spans, "closure defined here");
1764+
}
1765+
_ => {}
1766+
}
1767+
}
1768+
}

Diff for: src/test/ui/argument-suggestions/basic.rs

+3
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ fn main() {
2222
missing(); //~ ERROR this function takes
2323
swapped("", 1); //~ ERROR arguments to this function are incorrect
2424
permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect
25+
26+
let closure = |x| x;
27+
closure(); //~ ERROR this function takes
2528
}

Diff for: src/test/ui/argument-suggestions/basic.stderr

+19-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,23 @@ help: reorder these arguments
8181
LL | permuted(X {}, Y {}, Z {});
8282
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
8383

84-
error: aborting due to 5 previous errors
84+
error[E0057]: this function takes 1 argument but 0 arguments were supplied
85+
--> $DIR/basic.rs:27:5
86+
|
87+
LL | closure();
88+
| ^^^^^^^-- an argument is missing
89+
|
90+
note: closure defined here
91+
--> $DIR/basic.rs:26:19
92+
|
93+
LL | let closure = |x| x;
94+
| ^^^
95+
help: provide the argument
96+
|
97+
LL | closure({_});
98+
| ~~~~~~~~~~~~
99+
100+
error: aborting due to 6 previous errors
85101

86-
Some errors have detailed explanations: E0061, E0308.
87-
For more information about an error, try `rustc --explain E0061`.
102+
Some errors have detailed explanations: E0057, E0061, E0308.
103+
For more information about an error, try `rustc --explain E0057`.

Diff for: src/test/ui/error-codes/E0057.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
44
LL | let a = f();
55
| ^-- an argument is missing
66
|
7+
note: closure defined here
8+
--> $DIR/E0057.rs:2:13
9+
|
10+
LL | let f = |x| x * 3;
11+
| ^^^
712
help: provide the argument
813
|
914
LL | let a = f({_});
@@ -15,6 +20,11 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
1520
LL | let c = f(2, 3);
1621
| ^ - argument unexpected
1722
|
23+
note: closure defined here
24+
--> $DIR/E0057.rs:2:13
25+
|
26+
LL | let f = |x| x * 3;
27+
| ^^^
1828
help: remove the extra argument
1929
|
2030
LL | let c = f(2);

Diff for: src/test/ui/tuple/wrong_argument_ice-4.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ LL | | let b = 1;
88
LL | | });
99
| |_____- argument unexpected
1010
|
11+
note: closure defined here
12+
--> $DIR/wrong_argument_ice-4.rs:2:6
13+
|
14+
LL | (|| {})(|| {
15+
| ^^
1116
help: remove the extra argument
1217
|
1318
LL | (|| {})();

Diff for: src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | let z = f(1_usize, 2);
66
| |
77
| arguments to this function are incorrect
88
|
9+
note: closure defined here
10+
--> $DIR/unboxed-closures-type-mismatch.rs:4:17
11+
|
12+
LL | let mut f = |x: isize, y: isize| -> isize { x + y };
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
914
help: change the type of the numeric literal from `usize` to `isize`
1015
|
1116
LL | let z = f(1_isize, 2);

0 commit comments

Comments
 (0)