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)
downloadrust-b8708e2c9a264f1db74700c7471b8038e2d7f8da.tar.gz
rust-b8708e2c9a264f1db74700c7471b8038e2d7f8da.zip
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`.