about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJack Huey <31162821+jackh726@users.noreply.github.com>2022-04-16 15:38:32 -0400
committerJack Huey <31162821+jackh726@users.noreply.github.com>2022-05-06 16:55:53 -0400
commit15495767324ec173a01b6ff0197b5c4fceb61d21 (patch)
tree15d378c88403fb662c0f81e4e763c8a3714a5717
parent7bf47bfd32836dd2db6840b591014a90114245bb (diff)
downloadrust-15495767324ec173a01b6ff0197b5c4fceb61d21.tar.gz
rust-15495767324ec173a01b6ff0197b5c4fceb61d21.zip
Point at closure args too
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs11
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs122
-rw-r--r--src/test/ui/argument-suggestions/basic.rs3
-rw-r--r--src/test/ui/argument-suggestions/basic.stderr22
-rw-r--r--src/test/ui/error-codes/E0057.stderr10
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-4.stderr5
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr5
7 files changed, 97 insertions, 81 deletions
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 580fb7c3e0f..90b59df472c 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -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()
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 75976ebdf28..3a501196ed2 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -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");
+            }
+            _ => {}
+        }
+    }
+}
diff --git a/src/test/ui/argument-suggestions/basic.rs b/src/test/ui/argument-suggestions/basic.rs
index 765b2d5d68e..3e96322d67e 100644
--- a/src/test/ui/argument-suggestions/basic.rs
+++ b/src/test/ui/argument-suggestions/basic.rs
@@ -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
 }
diff --git a/src/test/ui/argument-suggestions/basic.stderr b/src/test/ui/argument-suggestions/basic.stderr
index 78f82b07619..8300a22c548 100644
--- a/src/test/ui/argument-suggestions/basic.stderr
+++ b/src/test/ui/argument-suggestions/basic.stderr
@@ -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({_});
+   |     ~~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0061, E0308.
-For more information about an error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0057, E0061, E0308.
+For more information about an error, try `rustc --explain E0057`.
diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr
index a151b20f865..4b4d30a8387 100644
--- a/src/test/ui/error-codes/E0057.stderr
+++ b/src/test/ui/error-codes/E0057.stderr
@@ -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);
diff --git a/src/test/ui/tuple/wrong_argument_ice-4.stderr b/src/test/ui/tuple/wrong_argument_ice-4.stderr
index 0c25b6801dc..f8dfc4cd043 100644
--- a/src/test/ui/tuple/wrong_argument_ice-4.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice-4.stderr
@@ -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 |     (|| {})();
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
index ea1ca380b1c..3241c9f8521 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
@@ -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);