Rollup merge of #104199 - SarthakSingh31:issue-97417-1, r=cjgillot
Keep track of the start of the argument block of a closure This removes a call to `tcx.sess.source_map()` from [compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs](https://github.com/rust-lang/rust/compare/master...SarthakSingh31:issue-97417-1?expand=1#diff-8406bbc0d0b43d84c91b1933305df896ecdba0d1f9269e6744f13d87a2ab268a) as required by #97417. VsCode automatically applied `rustfmt` to the files I edited under `src/tools`. I can undo that if its a problem. r? `@cjgillot`
This commit is contained in:
commit
c89bff29e5
15 changed files with 53 additions and 29 deletions
|
@ -71,7 +71,7 @@ pub trait InferCtxtExt<'tcx> {
|
|||
/// returns a span and `ArgKind` information that describes the
|
||||
/// arguments it expects. This can be supplied to
|
||||
/// `report_arg_count_mismatch`.
|
||||
fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>;
|
||||
fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>;
|
||||
|
||||
/// Reports an error when the number of arguments needed by a
|
||||
/// trait match doesn't match the number that the expression
|
||||
|
@ -83,6 +83,7 @@ pub trait InferCtxtExt<'tcx> {
|
|||
expected_args: Vec<ArgKind>,
|
||||
found_args: Vec<ArgKind>,
|
||||
is_closure: bool,
|
||||
closure_pipe_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
/// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
|
||||
|
@ -135,15 +136,16 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
/// returns a span and `ArgKind` information that describes the
|
||||
/// arguments it expects. This can be supplied to
|
||||
/// `report_arg_count_mismatch`.
|
||||
fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)> {
|
||||
fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let hir = self.tcx.hir();
|
||||
Some(match node {
|
||||
Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }),
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
|
||||
..
|
||||
}) => (
|
||||
fn_decl_span,
|
||||
fn_arg_span,
|
||||
hir.body(body)
|
||||
.params
|
||||
.iter()
|
||||
|
@ -174,6 +176,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
kind: hir::TraitItemKind::Fn(ref sig, _), ..
|
||||
}) => (
|
||||
sig.span,
|
||||
None,
|
||||
sig.decl
|
||||
.inputs
|
||||
.iter()
|
||||
|
@ -188,7 +191,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
),
|
||||
Node::Ctor(ref variant_data) => {
|
||||
let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
|
||||
(span, vec![ArgKind::empty(); variant_data.fields().len()])
|
||||
(span, None, vec![ArgKind::empty(); variant_data.fields().len()])
|
||||
}
|
||||
_ => panic!("non-FnLike node found: {:?}", node),
|
||||
})
|
||||
|
@ -204,6 +207,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
expected_args: Vec<ArgKind>,
|
||||
found_args: Vec<ArgKind>,
|
||||
is_closure: bool,
|
||||
closure_arg_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let kind = if is_closure { "closure" } else { "function" };
|
||||
|
||||
|
@ -241,24 +245,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
if let Some(found_span) = found_span {
|
||||
err.span_label(found_span, format!("takes {}", found_str));
|
||||
|
||||
// move |_| { ... }
|
||||
// ^^^^^^^^-- def_span
|
||||
//
|
||||
// move |_| { ... }
|
||||
// ^^^^^-- prefix
|
||||
let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
|
||||
// move |_| { ... }
|
||||
// ^^^-- pipe_span
|
||||
let pipe_span =
|
||||
if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
|
||||
|
||||
// Suggest to take and ignore the arguments with expected_args_length `_`s if
|
||||
// found arguments is empty (assume the user just wants to ignore args in this case).
|
||||
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
|
||||
if found_args.is_empty() && is_closure {
|
||||
let underscores = vec!["_"; expected_args.len()].join(", ");
|
||||
err.span_suggestion_verbose(
|
||||
pipe_span,
|
||||
closure_arg_span.unwrap_or(found_span),
|
||||
&format!(
|
||||
"consider changing the closure to take and ignore the expected argument{}",
|
||||
pluralize!(expected_args.len())
|
||||
|
@ -1252,13 +1245,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
obligation.cause.code(),
|
||||
)
|
||||
} else {
|
||||
let (closure_span, found) = found_did
|
||||
let (closure_span, closure_arg_span, found) = found_did
|
||||
.and_then(|did| {
|
||||
let node = self.tcx.hir().get_if_local(did)?;
|
||||
let (found_span, found) = self.get_fn_like_arguments(node)?;
|
||||
Some((Some(found_span), found))
|
||||
let (found_span, closure_arg_span, found) =
|
||||
self.get_fn_like_arguments(node)?;
|
||||
Some((Some(found_span), closure_arg_span, found))
|
||||
})
|
||||
.unwrap_or((found_span, found));
|
||||
.unwrap_or((found_span, None, found));
|
||||
|
||||
self.report_arg_count_mismatch(
|
||||
span,
|
||||
|
@ -1266,6 +1260,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
expected,
|
||||
found,
|
||||
found_trait_ty.is_closure(),
|
||||
closure_arg_span,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue