about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-08-12 16:50:46 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-08-12 16:50:46 -0700
commitb8708e2c9a264f1db74700c7471b8038e2d7f8da (patch)
tree72da3ca61fc26d7d41f8ddbcaeef9cd7aba8cf65
parent60960a260f7b5c695fd0717311d72ce62dd4eb43 (diff)
When needing type annotations in local bindings, account for impl Trait and closures
Do not suggest nonsensical types when the type inference is failing on
`impl Trait` or anonymous closures.
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs18
-rw-r--r--src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs18
-rw-r--r--src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr19
-rw-r--r--src/test/ui/inference/cannot-infer-async.rs16
-rw-r--r--src/test/ui/inference/cannot-infer-async.stderr11
-rw-r--r--src/test/ui/inference/cannot-infer-closure.rs6
-rw-r--r--src/test/ui/inference/cannot-infer-closure.stderr11
7 files changed, 97 insertions, 2 deletions
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 770d5155777..263b052e71f 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -151,12 +151,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         //   |         the type parameter `E` is specified
         // ```
         let (ty_msg, suffix) = match &local_visitor.found_ty {
-            Some(ty) if &ty.to_string() != "_" && name == "_" => {
+            Some(ty) if &ty.to_string() != "_" &&
+                name == "_" &&
+                // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized.
+                (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) &&
+                !ty.is_closure() => // The suggestion doesn't make sense for closures.
+            {
                 let ty = ty_to_string(ty);
                 (format!(" for `{}`", ty),
                  format!("the explicit type `{}`, with the type parameters specified", ty))
             }
-            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
+            Some(ty) if &ty.to_string() != "_" &&
+                ty.to_string() != name &&
+                // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized.
+                (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) &&
+                !ty.is_closure() => // The suggestion doesn't make sense for closures.
+            {
                 let ty = ty_to_string(ty);
                 (format!(" for `{}`", ty),
                  format!(
@@ -165,6 +175,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     name,
                  ))
             }
+            Some(ty) if ty.is_closure() => (
+                " for the closure".to_string(),
+                "a boxed closure type like `Box<Fn() -> _>`".to_string(),
+            ),
             _ => (String::new(), "a type".to_owned()),
         };
         let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
new file mode 100644
index 00000000000..fb6fd60c22f
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
@@ -0,0 +1,18 @@
+// edition:2018
+#![feature(async_await)]
+#![feature(impl_trait_in_bindings)]
+//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
+
+use std::io::Error;
+
+fn make_unit() -> Result<(), Error> { 
+    Ok(())
+}
+
+fn main() {
+    let fut = async {
+        make_unit()?; //~ ERROR type annotations needed
+        
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
new file mode 100644
index 00000000000..67a834a2e95
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
@@ -0,0 +1,19 @@
+warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:3:12
+   |
+LL | #![feature(impl_trait_in_bindings)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0282]: type annotations needed for `impl std::future::Future`
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:14:9
+   |
+LL |     let fut = async {
+   |         --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified
+LL |         make_unit()?;
+   |         ^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs
new file mode 100644
index 00000000000..354942121b0
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async.rs
@@ -0,0 +1,16 @@
+// edition:2018
+#![feature(async_await)]
+
+use std::io::Error;
+
+fn make_unit() -> Result<(), Error> { 
+    Ok(())
+}
+
+fn main() {
+    let fut = async {
+        make_unit()?; //~ ERROR type annotations needed
+        
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr
new file mode 100644
index 00000000000..36608a11bb7
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-async.rs:12:9
+   |
+LL |     let fut = async {
+   |         --- consider giving `fut` a type
+LL |         make_unit()?;
+   |         ^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs
new file mode 100644
index 00000000000..9c1e609ce64
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let x = || {
+        Err(())?; //~ ERROR type annotations needed for the closure
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr
new file mode 100644
index 00000000000..b8ca099aec1
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed for the closure
+  --> $DIR/cannot-infer-closure.rs:3:9
+   |
+LL |     let x = || {
+   |         - consider giving `x` a boxed closure type like `Box<Fn() -> _>`
+LL |         Err(())?;
+   |         ^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.