Point at closure args too

This commit is contained in:
Jack Huey 2022-04-16 15:38:32 -04:00
parent 7bf47bfd32
commit 1549576732
7 changed files with 97 additions and 81 deletions

View File

@ -59,7 +59,7 @@ pub fn check_legal_trait_for_method_call(
enum CallStep<'tcx> {
Builtin(Ty<'tcx>),
DeferredClosure(ty::FnSig<'tcx>),
DeferredClosure(DefId, ty::FnSig<'tcx>),
/// E.g., enum variant constructors.
Overloaded(MethodCallee<'tcx>),
}
@ -107,8 +107,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
}
Some(CallStep::DeferredClosure(fn_sig)) => {
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
Some(CallStep::DeferredClosure(def_id, fn_sig)) => {
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig)
}
Some(CallStep::Overloaded(method_callee)) => {
@ -171,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_substs: substs,
},
);
return Some(CallStep::DeferredClosure(closure_sig));
return Some(CallStep::DeferredClosure(def_id, closure_sig));
}
}
@ -533,6 +533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_expr: &'tcx hir::Expr<'tcx>,
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
closure_def_id: DefId,
fn_sig: ty::FnSig<'tcx>,
) -> Ty<'tcx> {
// `fn_sig` is the *signature* of the closure being called. We
@ -555,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::TupleArguments,
None,
Some(closure_def_id),
);
fn_sig.output()

View File

@ -24,7 +24,7 @@ use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span};
@ -523,24 +523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("arguments to this {} are incorrect", call_name),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();
for param in 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)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.emit();
break 'errors;
}
@ -558,24 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
DiagnosticId::Error(err_code.to_owned()),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();
for param in 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)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.multipart_suggestion(
"use parentheses to construct a tuple",
vec![(start, '('.to_string()), (end, ')'.to_string())],
@ -613,24 +579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("arguments to this {} are incorrect", call_name),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();
for param in 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)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.emit();
break 'errors;
}
@ -948,24 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.flat_map(|id| tcx.hir().body(id).params)
;
for param in 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)));
}
label_fn_like(tcx, &mut err, fn_def_id);
// And add a suggestion block for all of the parameters
let suggestion_text = match suggestion_text {
@ -1790,3 +1722,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
fn label_fn_like<'tcx>(
tcx: TyCtxt<'tcx>,
err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
def_id: Option<DefId>,
) {
let Some(def_id) = def_id else {
return;
};
if let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();
for param in 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)));
} else {
match tcx.hir().get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, _, _, span, ..),
..
})) => {
let spans: MultiSpan = (*span).into();
// Note: We don't point to param spans here because they overlap
// with the closure span itself
err.span_note(spans, "closure defined here");
}
_ => {}
}
}
}

View File

@ -22,4 +22,7 @@ fn main() {
missing(); //~ ERROR this function takes
swapped("", 1); //~ ERROR arguments to this function are incorrect
permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect
let closure = |x| x;
closure(); //~ ERROR this function takes
}

View File

@ -81,7 +81,23 @@ help: reorder these arguments
LL | permuted(X {}, Y {}, Z {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
error[E0057]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:27:5
|
LL | closure();
| ^^^^^^^-- an argument is missing
|
note: closure defined here
--> $DIR/basic.rs:26:19
|
LL | let closure = |x| x;
| ^^^
help: provide the argument
|
LL | closure({_});
| ~~~~~~~~~~~~
Some errors have detailed explanations: E0061, E0308.
For more information about an error, try `rustc --explain E0061`.
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0057, E0061, E0308.
For more information about an error, try `rustc --explain E0057`.

View File

@ -4,6 +4,11 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
LL | let a = f();
| ^-- an argument is missing
|
note: closure defined here
--> $DIR/E0057.rs:2:13
|
LL | let f = |x| x * 3;
| ^^^
help: provide the argument
|
LL | let a = f({_});
@ -15,6 +20,11 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
LL | let c = f(2, 3);
| ^ - argument unexpected
|
note: closure defined here
--> $DIR/E0057.rs:2:13
|
LL | let f = |x| x * 3;
| ^^^
help: remove the extra argument
|
LL | let c = f(2);

View File

@ -8,6 +8,11 @@ LL | | let b = 1;
LL | | });
| |_____- argument unexpected
|
note: closure defined here
--> $DIR/wrong_argument_ice-4.rs:2:6
|
LL | (|| {})(|| {
| ^^
help: remove the extra argument
|
LL | (|| {})();

View File

@ -6,6 +6,11 @@ LL | let z = f(1_usize, 2);
| |
| arguments to this function are incorrect
|
note: closure defined here
--> $DIR/unboxed-closures-type-mismatch.rs:4:17
|
LL | let mut f = |x: isize, y: isize| -> isize { x + y };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: change the type of the numeric literal from `usize` to `isize`
|
LL | let z = f(1_isize, 2);