rust/src/test/ui/impl-trait/where-allowed.rs
Aaron Hill 0e2ccaaa3e
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.
2019-11-18 14:01:36 -05:00

224 lines
7.3 KiB
Rust

//! A simple test for testing many permutations of allowedness of
//! impl Trait
use std::fmt::Debug;
// Allowed
fn in_parameters(_: impl Debug) { panic!() }
// Allowed
fn in_return() -> impl Debug { panic!() }
// Allowed
fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
// Disallowed
fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_impl_Fn_parameter_in_parameters(_: &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
// Disallowed
fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
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
// Disallowed
fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Allowed
fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }
// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
vec![vec![0; 10], vec![12; 7], vec![8; 3]]
}
// Disallowed
struct InBraceStructField { x: impl Debug }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
struct InAdtInBraceStructField { x: Vec<impl Debug> }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
struct InTupleStructField(impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
// Disallowed
enum InEnum {
InBraceVariant { x: impl Debug },
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
InTupleVariant(impl Debug),
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Allowed
trait InTraitDefnParameters {
fn in_parameters(_: impl Debug);
}
// Disallowed
trait InTraitDefnReturn {
fn in_return() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Allowed and disallowed in trait impls
trait DummyTrait {
type Out;
fn in_trait_impl_parameter(_: impl Debug);
fn in_trait_impl_return() -> Self::Out;
}
impl DummyTrait for () {
type Out = impl Debug;
//~^ ERROR `impl Trait` in type aliases is unstable
//~^^ ERROR could not find defining uses
fn in_trait_impl_parameter(_: impl Debug) { }
// Allowed
fn in_trait_impl_return() -> impl Debug { () }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Allowed
struct DummyType;
impl DummyType {
fn in_inherent_impl_parameters(_: impl Debug) { }
fn in_inherent_impl_return() -> impl Debug { () }
}
// Disallowed
extern "C" {
fn in_foreign_parameters(_: impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
fn in_foreign_return() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Allowed
extern "C" fn in_extern_fn_parameters(_: impl Debug) {
}
// Allowed
extern "C" fn in_extern_fn_return() -> impl Debug {
22
}
type InTypeAlias<R> = impl Debug;
//~^ ERROR `impl Trait` in type aliases is unstable
//~^^ ERROR could not find defining uses
type InReturnInTypeAlias<R> = fn() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
//~| ERROR `impl Trait` in type aliases is unstable
// Disallowed in impl headers
impl PartialEq<impl Debug> for () {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Disallowed in impl headers
impl PartialEq<()> for impl Debug {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Disallowed in inherent impls
impl impl Debug {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Disallowed in inherent impls
struct InInherentImplAdt<T> { t: T }
impl InInherentImplAdt<impl Debug> {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Disallowed in where clauses
fn in_fn_where_clause()
where impl Debug: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}
// Disallowed in where clauses
fn in_adt_in_fn_where_clause()
where Vec<impl Debug>: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}
// Disallowed
fn in_trait_parameter_in_fn_where_clause<T>()
where T: PartialEq<impl Debug>
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}
// Disallowed
fn in_Fn_parameter_in_fn_where_clause<T>()
where T: Fn(impl Debug)
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}
// Disallowed
fn in_Fn_return_in_fn_where_clause<T>()
where T: Fn() -> impl Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}
fn main() {
let _in_local_variable: impl Fn() = || {};
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
let _in_return_in_local_variable = || -> impl Fn() { || {} };
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}