about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-10-25 23:23:15 +0000
committerEsteban Küber <esteban@kuber.com.ar>2025-01-30 18:38:41 +0000
commit03e9a383906ca85e264f056f490c091fdef30a90 (patch)
treebc72cc6ff320fc60f1c7db960a326f4d838555cd
parentd3a148fe07bf2bcab0d262463f0f892f555e0aa6 (diff)
downloadrust-03e9a383906ca85e264f056f490c091fdef30a90.tar.gz
rust-03e9a383906ca85e264f056f490c091fdef30a90.zip
On E0271 for a closure behind a binding, point at binding in call too
```
error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
    --> tests/ui/closures/return-type-doesnt-match-bound.rs:18:20
     |
18   |     let c = |e| -> ! { //~ ERROR to be a closure that returns
     |             -------^
     |                    |
     |                    expected `Result<(), _>`, found `!`
...
22   |     f().or_else(c);
     |         ------- -
     |         |
     |         required by a bound introduced by this call
     |
     = note: expected enum `Result<(), _>`
                found type `!`
note: required by a bound in `Result::<T, E>::or_else`
    --> /home/gh-estebank/rust/library/core/src/result.rs:1406:39
     |
1406 |     pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
     |                                       ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else`
```
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--tests/ui/closures/return-type-doesnt-match-bound.rs25
-rw-r--r--tests/ui/closures/return-type-doesnt-match-bound.stderr35
3 files changed, 64 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 24615dfdc56..78f6cd9e656 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1424,6 +1424,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 //    |                 ^^^^^ expected `Unit3`, found `Unit4`
                 //    |
                 diag.span_label(span, "");
+                if !span.overlaps(obligation.cause.span) {
+                    // Point at the binding corresponding to the closure where it is used.
+                    diag.span_label(obligation.cause.span, "");
+                }
             }
 
             let secondary_span = (|| {
diff --git a/tests/ui/closures/return-type-doesnt-match-bound.rs b/tests/ui/closures/return-type-doesnt-match-bound.rs
new file mode 100644
index 00000000000..f9098d0cb5c
--- /dev/null
+++ b/tests/ui/closures/return-type-doesnt-match-bound.rs
@@ -0,0 +1,25 @@
+use std::error::Error;
+use std::process::exit;
+
+fn foo<F>(f: F) -> ()
+where
+    F: FnOnce() -> Result<(), Box<dyn Error>>,
+{
+    f().or_else(|e| -> ! { //~ ERROR to be a closure that returns
+        eprintln!("{:?}", e);
+        exit(1)
+    });
+}
+
+fn bar<F>(f: F) -> ()
+where
+    F: FnOnce() -> Result<(), Box<dyn Error>>,
+{
+    let c = |e| -> ! { //~ ERROR to be a closure that returns
+        eprintln!("{:?}", e);
+        exit(1)
+    };
+    f().or_else(c);
+}
+
+fn main() {}
diff --git a/tests/ui/closures/return-type-doesnt-match-bound.stderr b/tests/ui/closures/return-type-doesnt-match-bound.stderr
new file mode 100644
index 00000000000..c6aad2054f5
--- /dev/null
+++ b/tests/ui/closures/return-type-doesnt-match-bound.stderr
@@ -0,0 +1,35 @@
+error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:8:17}` to be a closure that returns `Result<(), _>`, but it returns `!`
+  --> $DIR/return-type-doesnt-match-bound.rs:8:24
+   |
+LL |     f().or_else(|e| -> ! {
+   |         ------- -------^
+   |         |              |
+   |         |              expected `Result<(), _>`, found `!`
+   |         required by a bound introduced by this call
+   |
+   = note: expected enum `Result<(), _>`
+              found type `!`
+note: required by a bound in `Result::<T, E>::or_else`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+
+error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
+  --> $DIR/return-type-doesnt-match-bound.rs:18:20
+   |
+LL |     let c = |e| -> ! {
+   |             -------^
+   |                    |
+   |                    expected `Result<(), _>`, found `!`
+...
+LL |     f().or_else(c);
+   |         ------- -
+   |         |
+   |         required by a bound introduced by this call
+   |
+   = note: expected enum `Result<(), _>`
+              found type `!`
+note: required by a bound in `Result::<T, E>::or_else`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.