about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-08-18 13:27:08 +0000
committerMichael Goulet <michael@errs.io>2022-08-21 02:35:11 +0000
commit5212ac9dac4c99714ca7379f7882109fb1f07405 (patch)
tree9e3dfbb6d98fffb536621143361312a3961d8c36
parentd2f54b1990c916c1af15124ce45dbdaa9758f7b2 (diff)
downloadrust-5212ac9dac4c99714ca7379f7882109fb1f07405.tar.gz
rust-5212ac9dac4c99714ca7379f7882109fb1f07405.zip
Make check for overlapping closure span more accurate
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs55
-rw-r--r--src/test/ui/issues/issue-69683.stderr28
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr6
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs1
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr6
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr6
6 files changed, 46 insertions, 56 deletions
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 41314644a81..3642b2ab03b 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -1669,6 +1669,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
             = *error.obligation.cause.code().peel_derives() else { return false; };
+        let hir = self.tcx.hir();
+        let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
 
         // Skip over mentioning async lang item
         if Some(def_id) == self.tcx.lang_items().from_generator_fn()
@@ -1677,15 +1679,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             return false;
         }
-        // Skip over closure arg mismatch, which has a better heuristic
-        // to determine what span to point at.
-        if let traits::FulfillmentErrorCode::CodeSelectionError(
-            traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
-        ) = error.code
-            && let ty::Closure(..) | ty::Generator(..) = expected.skip_binder().self_ty().kind()
-        {
-            return false;
-        }
 
         let Some(unsubstituted_pred) =
             self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
@@ -1741,16 +1734,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
         }
 
-        let hir = self.tcx.hir();
-        match hir.get(hir_id) {
-            hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Path(qpath), hir_id, .. }) => {
+        if self.closure_span_overlaps_error(error, expr.span) {
+            return false;
+        }
+
+        match &expr.kind {
+            hir::ExprKind::Path(qpath) => {
                 if let hir::Node::Expr(hir::Expr {
                     kind: hir::ExprKind::Call(callee, args),
                     hir_id: call_hir_id,
+                    span: call_span,
                     ..
-                }) = hir.get(hir.get_parent_node(*hir_id))
-                    && callee.hir_id == *hir_id
+                }) = hir.get(hir.get_parent_node(expr.hir_id))
+                    && callee.hir_id == expr.hir_id
                 {
+                    if self.closure_span_overlaps_error(error, *call_span) {
+                        return false;
+                    }
+
                     for param in
                         [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
                         .into_iter()
@@ -1780,10 +1781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
-            hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::MethodCall(segment, args, ..),
-                ..
-            }) => {
+            hir::ExprKind::MethodCall(segment, args, ..) => {
                 for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
                     .into_iter()
                     .flatten()
@@ -1805,9 +1803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     return true;
                 }
             }
-            hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Struct(qpath, fields, ..), ..
-            }) => {
+            hir::ExprKind::Struct(qpath, fields, ..) => {
                 if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
                     self.typeck_results.borrow().qpath_res(qpath, hir_id)
                 {
@@ -1839,6 +1835,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         false
     }
 
+    fn closure_span_overlaps_error(
+        &self,
+        error: &traits::FulfillmentError<'tcx>,
+        span: Span,
+    ) -> bool {
+        if let traits::FulfillmentErrorCode::CodeSelectionError(
+            traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
+        ) = error.code
+            && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
+            && span.overlaps(self.tcx.def_span(*def_id))
+        {
+            true
+        } else {
+            false
+        }
+    }
+
     fn point_at_arg_if_possible(
         &self,
         error: &mut traits::FulfillmentError<'tcx>,
diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr
index 248fb75b4c4..193de1a35cf 100644
--- a/src/test/ui/issues/issue-69683.stderr
+++ b/src/test/ui/issues/issue-69683.stderr
@@ -37,33 +37,7 @@ help: try using a fully qualified path to specify the expected types
 LL |     <u16 as Foo<I>>::foo(0u16, b);
    |     +++++++++++++++++++++    ~
 
-error[E0283]: type annotations needed
-  --> $DIR/issue-69683.rs:30:10
-   |
-LL |     0u16.foo(b);
-   |     ---- ^^^
-   |     |
-   |     type must be known at this point
-   |
-note: multiple `impl`s satisfying `u8: Element<_>` found
-  --> $DIR/issue-69683.rs:5:1
-   |
-LL | impl<T> Element<()> for T {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | impl<T: Element<S>, S> Element<[S; 3]> for T {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required for `u16` to implement `Foo<_>`
-  --> $DIR/issue-69683.rs:20:9
-   |
-LL | impl<I> Foo<I> for u16
-   |         ^^^^^^     ^^^
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <u16 as Foo<I>>::foo(0u16, b);
-   |     +++++++++++++++++++++    ~
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0283, E0284.
 For more information about an error, try `rustc --explain E0283`.
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index a6ed22781e9..a02ec819838 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -133,12 +133,14 @@ LL |         F: FnMut(Self::Item) -> B,
    |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
-  --> $DIR/closure-arg-count.rs:27:53
+  --> $DIR/closure-arg-count.rs:27:57
    |
 LL |     let bar = |i, x, y| i;
    |               --------- takes 3 distinct arguments
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
-   |                                                     ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
index 0d64ded215a..8dbe3472ea8 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
@@ -17,5 +17,6 @@ pub fn main() {
     //~^ ERROR type mismatch
     //~| NOTE expected due to this
     //~| NOTE expected closure signature `fn(isize, _) -> _`
+    //~| NOTE required by a bound introduced by this call
     println!("{}", z);
 }
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 0b0d9f10786..54b22006527 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -1,11 +1,13 @@
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/unboxed-closures-vtable-mismatch.rs:16:13
+  --> $DIR/unboxed-closures-vtable-mismatch.rs:16:24
    |
 LL |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
    |                       ----------------------------- found signature defined here
 LL |
 LL |     let z = call_it(3, f);
-   |             ^^^^^^^ expected due to this
+   |             -------    ^ expected due to this
+   |             |
+   |             required by a bound introduced by this call
    |
    = note: expected closure signature `fn(isize, _) -> _`
               found closure signature `fn(usize, _) -> _`
diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
index d8e9776bb00..9a24fb8c2be 100644
--- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
@@ -1,10 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/non-tupled-arg-mismatch.rs:6:7
+  --> $DIR/non-tupled-arg-mismatch.rs:6:5
    |
 LL |     a(|_: usize| {});
-   |     - ^^^^^^^^^^^^^ types differ
-   |     |
-   |     required by a bound introduced by this call
+   |     ^ types differ
    |
    = note: expected trait `Fn<usize>`
               found trait `Fn<(usize,)>`