about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2019-11-14 20:19:34 -0500
committerAaron Hill <aa1ronham@gmail.com>2019-11-18 14:01:36 -0500
commit0e2ccaaa3e70d85d1243c07e6ac0ef3829115a8d (patch)
tree752bbf3236269b21bff14e63be3efefe643f6e88 /src/test
parent1bd30ce2aac40c7698aa4a1b9520aa649ff2d1c5 (diff)
downloadrust-0e2ccaaa3e70d85d1243c07e6ac0ef3829115a8d.tar.gz
rust-0e2ccaaa3e70d85d1243c07e6ac0ef3829115a8d.zip
Fix 'type annotations needed' error with opaque types
Related: #66426

This commit adds handling for opaque types during inference variable
fallback. Type variables generated from the instantiatino of opaque
types now fallback to the opque type itself.

Normally, the type variable for an instantiated opaque type is either
unified with the concrete type, or with the opaque type itself (e.g when
a function returns an opaque type by calling another function).

However, it's possible for the type variable to be left completely
unconstrained. This can occur in code like this:

```rust
pub type Foo = impl Copy;
fn produce() -> Option<Foo> {
    None
}
```

Here, we'll instantatiate the `Foo` in `Option<Foo>` to a fresh type
variable, but we will never unify it with anything due to the fact
that we return a `None`.

This results in the error message:

`type annotations needed: cannot resolve `_: std::marker::Copy``

pointing at `pub type Foo = impl Copy`.

This message is not only confusing, it's incorrect. When an opaque type
inference variable is completely unconstrained, we can always fall back
to using the opaque type itself. This effectively turns that particular
use of the opaque type into a non-defining use, even if it appears in a
defining scope.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.rs9
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.stderr11
-rw-r--r--src/test/ui/impl-trait/where-allowed.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/fallback.rs22
4 files changed, 42 insertions, 5 deletions
diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs
new file mode 100644
index 00000000000..f7744ef1b3e
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed-2.rs
@@ -0,0 +1,9 @@
+//! Ideally, these tests would go in `where-allowed.rs`, but we bail out
+//! too early to display them.
+use std::fmt::Debug;
+
+// Disallowed
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
+//~^ ERROR opaque type expands to a recursive type
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
new file mode 100644
index 00000000000..1de15014c1f
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed-2.stderr
@@ -0,0 +1,11 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/where-allowed-2.rs:6:30
+   |
+LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
+   |                              ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs
index 5ab74e02e0e..211a14ed4dd 100644
--- a/src/test/ui/impl-trait/where-allowed.rs
+++ b/src/test/ui/impl-trait/where-allowed.rs
@@ -12,10 +12,6 @@ fn in_return() -> impl Debug { panic!() }
 fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
 
 // Disallowed
-fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-//~^ ERROR type annotations needed
-
-// Disallowed
 fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
 //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
 
@@ -60,7 +56,6 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
 fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
 //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
 //~| ERROR nested `impl Trait` is not allowed
-//~| ERROR type annotations needed
 
 // Disallowed
 fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
diff --git a/src/test/ui/type-alias-impl-trait/fallback.rs b/src/test/ui/type-alias-impl-trait/fallback.rs
new file mode 100644
index 00000000000..c59c1e3b7d0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/fallback.rs
@@ -0,0 +1,22 @@
+// Tests that we correctly handle the instantiated
+// inference variable being completely unconstrained.
+//
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Copy;
+
+enum Wrapper<T> {
+    First(T),
+    Second
+}
+
+fn _make_iter() -> Foo {
+    true
+}
+
+fn _produce() -> Wrapper<Foo> {
+    Wrapper::Second
+}
+
+fn main() {}