1
Fork 0

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");
}
_ => {}
}
}
}