diff options
Diffstat (limited to 'tests/ui/type-alias-impl-trait')
314 files changed, 6648 insertions, 0 deletions
diff --git a/tests/ui/type-alias-impl-trait/argument-types.rs b/tests/ui/type-alias-impl-trait/argument-types.rs new file mode 100644 index 000000000..185207b98 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/argument-types.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] +// check-pass +use std::fmt::Debug; + +type Foo = impl Debug; + +fn foo1(mut x: Foo) { + x = 22_u32; +} + +fn foo2(mut x: Foo) { + // no constraint on x +} + +fn foo3(x: Foo) { + println!("{:?}", x); +} + +fn foo_value() -> Foo { + 11_u32 +} + +fn main() { + foo3(foo_value()); +} diff --git a/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs new file mode 100644 index 000000000..703e3e869 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// build-pass + +trait T { type Item; } + +type Alias<'a> = impl T<Item = &'a ()>; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-const.rs b/tests/ui/type-alias-impl-trait/assoc-type-const.rs new file mode 100644 index 000000000..0ade36daf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-const.rs @@ -0,0 +1,32 @@ +// Tests that we properly detect defining usages when using +// const generics in an associated opaque type +// check-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt<'a, const C: usize> { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct<const C: usize> {} + +trait MyTrait<'a, const C: usize> { + type MyItem; + const MY_CONST: usize; +} + +impl<'a, const C: usize> MyTrait<'a, C> for MyStruct<C> { + type MyItem = u8; + const MY_CONST: usize = C; +} + +impl<'a, I, const C: usize> UnwrapItemsExt<'a, C> for I { + type Iter = impl MyTrait<'a, C>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct::<C> {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs new file mode 100644 index 000000000..3f34b00ec --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs @@ -0,0 +1,26 @@ +// Tests that we don't allow unconstrained lifetime parameters in impls when +// the lifetime is used in an associated opaque type. + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a> {} + +impl<'a> MyTrait<'a> for MyStruct {} + +impl<'a, I> UnwrapItemsExt for I { + //~^ ERROR the lifetime parameter `'a` is not constrained + type Iter = impl MyTrait<'a>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr new file mode 100644 index 000000000..e594dc577 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/assoc-type-lifetime-unconstrained.rs:17:6 + | +LL | impl<'a, I> UnwrapItemsExt for I { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs new file mode 100644 index 000000000..39f785d8c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs @@ -0,0 +1,26 @@ +// Tests that we still detect defining usages when +// lifetimes are used in an associated opaque type +// check-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt<'a> { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a> {} + +impl<'a> MyTrait<'a> for MyStruct {} + +impl<'a, I> UnwrapItemsExt<'a> for I { + type Iter = impl MyTrait<'a>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs new file mode 100644 index 000000000..42f07d49f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +// build-pass (FIXME(62277): could be check-pass?) + +trait Bar {} +struct Dummy; +impl Bar for Dummy {} + +trait Foo { + type Assoc: Bar; + fn foo() -> Self::Assoc; + fn bar() -> Self::Assoc; +} + +type Helper = impl Bar; + +impl Foo for i32 { + type Assoc = Helper; + fn foo() -> Helper { + Dummy + } + fn bar() -> Helper { + Dummy + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs new file mode 100644 index 000000000..962606508 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs @@ -0,0 +1,20 @@ +//check-pass + +#![feature(type_alias_impl_trait)] + +trait Trait { + type Opaque1; + type Opaque2; + fn constrain(self); +} + +impl<'a> Trait for &'a () { + type Opaque1 = impl Sized; + type Opaque2 = impl Sized + 'a; + fn constrain(self) { + let _: Self::Opaque1 = (); + let _: Self::Opaque2 = self; + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs new file mode 100644 index 000000000..a1584581e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + type Foo = impl std::fmt::Debug; + + pub fn foo() -> Foo { + 22_u32 + } +} + +fn is_send<T: Send>(_: T) {} + +fn main() { + is_send(m::foo()); +} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs new file mode 100644 index 000000000..fc89b0e87 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + use std::rc::Rc; + + type Foo = impl std::fmt::Debug; //~ NOTE appears within the type + //~^ within this `Foo` + //~| expansion of desugaring + + pub fn foo() -> Foo { + Rc::new(22_u32) + } +} + +fn is_send<T: Send>(_: T) {} +//~^ required by this bound +//~| required by a bound + +fn main() { + is_send(m::foo()); + //~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277] + //~| NOTE cannot be sent + //~| NOTE required by a bound +} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr new file mode 100644 index 000000000..d7247302d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -0,0 +1,26 @@ +error[E0277]: `Rc<u32>` cannot be sent between threads safely + --> $DIR/auto-trait-leakage2.rs:21:13 + | +LL | type Foo = impl std::fmt::Debug; + | -------------------- within this `Foo` +... +LL | is_send(m::foo()); + | ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>` +note: required because it appears within the type `Foo` + --> $DIR/auto-trait-leakage2.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/auto-trait-leakage2.rs:16:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs new file mode 100644 index 000000000..5fb7a9473 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME This should compile, but it currently doesn't + +mod m { + type Foo = impl std::fmt::Debug; + //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + + pub fn foo() -> Foo { + 22_u32 + } + + pub fn bar() { + is_send(foo()); + } + + fn is_send<T: Send>(_: T) {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr new file mode 100644 index 000000000..1e9a45aac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -0,0 +1,22 @@ +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:15:9 + | +LL | is_send(foo()); + | ^^^^^^^ + = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs b/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs new file mode 100644 index 000000000..712ed5543 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs @@ -0,0 +1,9 @@ +pub trait SomeTrait {} + +impl SomeTrait for () {} + +// Adding this `impl` would cause errors in this crate's dependent, +// so it would be a breaking change. We explicitly don't add this impl, +// as the dependent crate already assumes this impl exists and thus already +// does not compile. +//impl SomeTrait for i32 {} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs b/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs new file mode 100644 index 000000000..75d20a6fe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +// edition:2018 + +use std::future::Future; + +pub trait Service<Request> { + type Future: Future<Output = ()>; + fn call(&mut self, req: Request) -> Self::Future; +} + +// NOTE: the pub(crate) here is critical +pub(crate) fn new() -> () {} + +pub struct A; +impl Service<()> for A { + type Future = impl Future<Output = ()>; + fn call(&mut self, _: ()) -> Self::Future { + async { new() } + } +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs new file mode 100644 index 000000000..e7bca2231 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs @@ -0,0 +1,10 @@ +// Crate that exports an opaque `impl Trait` type. Used for testing cross-crate. + +#![crate_type = "rlib"] +#![feature(type_alias_impl_trait)] + +pub type Foo = impl std::fmt::Debug; + +pub fn foo() -> Foo { + 5 +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs new file mode 100644 index 000000000..119f7df1f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs @@ -0,0 +1,20 @@ +// Crate that exports an opaque `impl Trait` type. Used for testing cross-crate. + +#![crate_type = "rlib"] +#![feature(type_alias_impl_trait)] + +pub trait View { + type Tmp: Iterator<Item = u32>; + + fn test(&self) -> Self::Tmp; +} + +pub struct X; + +impl View for X { + type Tmp = impl Iterator<Item = u32>; + + fn test(&self) -> Self::Tmp { + vec![1, 2, 3].into_iter() + } +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs b/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs new file mode 100644 index 000000000..52802dd8f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs @@ -0,0 +1,2 @@ +pub trait ForeignTrait {} +pub struct ForeignType<T>(pub T); diff --git a/tests/ui/type-alias-impl-trait/bound_reduction.rs b/tests/ui/type-alias-impl-trait/bound_reduction.rs new file mode 100644 index 000000000..b9b50f0b7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(warnings)] +#![feature(type_alias_impl_trait)] + +fn main() { +} + +type Foo<V> = impl std::fmt::Debug; + +trait Trait<U> {} + +fn foo_desugared<T: Trait<[u32; { + #[no_mangle] + static FOO: usize = 42; + 3 +}]>>(_: T) -> Foo<T> { + (42, std::marker::PhantomData::<T>) +} diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs new file mode 100644 index 000000000..0bcc9e002 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait TraitWithAssoc { + type Assoc; +} + +type Foo<V> = impl Trait<V>; + +trait Trait<U> {} + +impl<W> Trait<W> for () {} + +fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { + () + //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` +} diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr new file mode 100644 index 000000000..3c259bd9e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` + --> $DIR/bound_reduction2.rs:16:5 + | +LL | type Foo<V> = impl Trait<V>; + | - this generic parameter must be used with a generic type parameter +... +LL | () + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs new file mode 100644 index 000000000..55b4dc8dc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs @@ -0,0 +1,19 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X<T> = impl Clone; + +fn f<T: Clone>(t: T) -> X<T> { + t + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +fn g<T>(o: Option<X<T>>) -> Option<X<T>> { + o.clone() +} + +fn main() { + g(None::<X<&mut ()>>); +} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr new file mode 100644 index 000000000..8678e9b33 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/bounds-are-checked-2.rs:9:5 + | +LL | t + | ^ the trait `Clone` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type X<T: std::clone::Clone> = impl Clone; + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs new file mode 100644 index 000000000..83d22161e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -0,0 +1,24 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X<'a> = impl Into<&'static str> + From<&'a str>; + +fn f<'a: 'static>(t: &'a str) -> X<'a> { + //~^ WARNING unnecessary lifetime parameter + t + //~^ ERROR non-defining opaque type use +} + +fn extend_lt<'a>(o: &'a str) -> &'static str { + X::<'_>::from(o).into() +} + +fn main() { + let r = { + let s = "abcdef".to_string(); + extend_lt(&s) + }; + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr new file mode 100644 index 000000000..920eef11d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -0,0 +1,19 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/bounds-are-checked.rs:8:6 + | +LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error: non-defining opaque type use in defining scope + --> $DIR/bounds-are-checked.rs:10:5 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | t + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs new file mode 100644 index 000000000..c5e7af81d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_args.rs @@ -0,0 +1,16 @@ +// check-pass + +// regression test for https://github.com/rust-lang/rust/issues/100800 + +#![feature(type_alias_impl_trait)] + +trait Anything {} +impl<T> Anything for T {} +type Input = impl Anything; +fn run<F: FnOnce(Input) -> ()>(f: F, i: Input) { + f(i); +} + +fn main() { + run(|x: u32| {println!("{x}");}, 0); +} diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs new file mode 100644 index 000000000..82386c280 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_args2.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +trait Foo { + // This was reachable in https://github.com/rust-lang/rust/issues/100800 + fn foo(&self) { unreachable!() } +} +impl<T> Foo for T {} + +struct B; +impl B { + fn foo(&self) {} +} + +type Input = impl Foo; +fn run1<F: FnOnce(Input)>(f: F, i: Input) {f(i)} +fn run2<F: FnOnce(B)>(f: F, i: B) {f(i)} + +fn main() { + run1(|x: B| {x.foo()}, B); + run2(|x: B| {x.foo()}, B); +} diff --git a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs new file mode 100644 index 000000000..475f4724f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs @@ -0,0 +1,65 @@ +// When WF checking the hidden type in the ParamEnv of the opaque type, +// one complication arises when the hidden type is a closure/generator: +// the "parent_substs" of the type may reference lifetime parameters +// not present in the opaque type. +// These region parameters are not really useful in this check. +// So here we ignore them and replace them with fresh region variables. + +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// Basic test +mod test1 { + // Hidden type = Closure['_#0r] + type Opaque = impl Sized; + + fn define<'a: 'a>() -> Opaque { + || {} + } +} + +// the region vars cannot both be equal to `'static` or `'empty` +mod test2 { + trait Trait {} + + // Hidden type = Closure['a, '_#0r, '_#1r] + // Constraints = [('_#0r: 'a), ('a: '_#1r)] + type Opaque<'a> + where + &'a (): Trait, + = impl Sized + 'a; + + fn define<'a, 'x, 'y>() -> Opaque<'a> + where + &'a (): Trait, + 'x: 'a, + 'a: 'y, + { + || {} + } +} + +// the region var cannot be equal to `'a` or `'b` +mod test3 { + trait Trait {} + + // Hidden type = Closure['a, 'b, '_#0r] + // Constraints = [('_#0r: 'a), ('_#0r: 'b)] + type Opaque<'a, 'b> + where + (&'a (), &'b ()): Trait, + = impl Sized + 'a + 'b; + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + (&'a (), &'b ()): Trait, + 'x: 'a, + 'x: 'b, + { + || {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs new file mode 100644 index 000000000..53974dbb3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs @@ -0,0 +1,65 @@ +// If the hidden type is a closure, we require the "outlives" bounds that appear on the +// defining site to also appear on the opaque type. +// +// It's not clear if this is the desired behavior but at least +// it's consistent and has no back-compat risk. + +// check-fail + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// requires `'a: 'b` bound +mod test1 { + type Opaque<'a, 'b> = impl Sized + 'a + 'b; + //~^ ERROR lifetime bound not satisfied + + fn define<'a, 'b>() -> Opaque<'a, 'b> + where + 'a: 'b, + { + || {} + } +} + +// Same as the above but through indirection `'x` +mod test2 { + type Opaque<'a, 'b> = impl Sized + 'a + 'b; + //~^ ERROR cannot infer an appropriate lifetime + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + 'a: 'x, + 'x: 'b, + { + || {} + } +} + +// fixed version of the above +mod test2_fixed { + type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b; + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + 'a: 'x, + 'x: 'b, + { + || {} + } +} + +// requires `T: 'static` +mod test3 { + type Opaque<T> = impl Sized; + //~^ ERROR the parameter type `T` may not live long enough + + fn define<T>() -> Opaque<T> + where + T: 'static, + { + || {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr new file mode 100644 index 000000000..ae6462bb6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -0,0 +1,64 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/closure_wf_outlives.rs:14:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/closure_wf_outlives.rs:14:17 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here + --> $DIR/closure_wf_outlives.rs:14:21 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/closure_wf_outlives.rs:27:17 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ +note: but, the lifetime must be valid for the lifetime `'b` as defined here... + --> $DIR/closure_wf_outlives.rs:27:21 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/closure_wf_outlives.rs:54:22 + | +LL | type Opaque<T> = impl Sized; + | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/closure_wf_outlives.rs:59:12 + | +LL | T: 'static, + | ^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | type Opaque<T: 'static> = impl Sized; + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0310, E0478, E0495. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.rs b/tests/ui/type-alias-impl-trait/closures_in_branches.rs new file mode 100644 index 000000000..7bb490bbe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closures_in_branches.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::ops::FnOnce(String) -> usize; + +fn foo(b: bool) -> Foo { + if b { + |x| x.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + + +type Foo1 = impl std::ops::FnOnce(String) -> usize; +fn foo1(b: bool) -> Foo1 { + |x| x.len() +} + +fn bar(b: bool) -> impl std::ops::FnOnce(String) -> usize { + if b { + |x| x.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + +fn bar1(b: bool) -> impl std::ops::FnOnce(String) -> usize { + |x| x.len() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.stderr b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr new file mode 100644 index 000000000..9cc15f14a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/closures_in_branches.rs:7:10 + | +LL | |x| x.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |x: /* Type */| x.len() + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/closures_in_branches.rs:21:10 + | +LL | |x| x.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |x: /* Type */| x.len() + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs new file mode 100644 index 000000000..077a31494 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.rs @@ -0,0 +1,17 @@ +// aux-build:foreign-crate.rs +#![feature(type_alias_impl_trait)] + +extern crate foreign_crate; + +trait LocalTrait {} +impl<T> LocalTrait for foreign_crate::ForeignType<T> {} + +type AliasOfForeignType<T> = impl LocalTrait; +fn use_alias<T>(val: T) -> AliasOfForeignType<T> { + foreign_crate::ForeignType(val) +} + +impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {} +//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr new file mode 100644 index 000000000..00b0dbbb5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence.rs:14:1 + | +LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- + | | | + | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs new file mode 100644 index 000000000..a63e0a1ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs @@ -0,0 +1,24 @@ +// aux-build: coherence_cross_crate_trait_decl.rs +// This test ensures that adding an `impl SomeTrait for i32` within +// `coherence_cross_crate_trait_decl` is not a breaking change, by +// making sure that even without such an impl this test fails to compile. + +#![feature(type_alias_impl_trait)] + +extern crate coherence_cross_crate_trait_decl; + +use coherence_cross_crate_trait_decl::SomeTrait; + +trait OtherTrait {} + +type Alias = impl SomeTrait; + +fn constrain() -> Alias { + () +} + +impl OtherTrait for Alias {} +impl OtherTrait for i32 {} +//~^ ERROR: conflicting implementations of trait `OtherTrait` for type `Alias` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr new file mode 100644 index 000000000..63a3ce29c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `OtherTrait` for type `Alias` + --> $DIR/coherence_cross_crate.rs:21:1 + | +LL | impl OtherTrait for Alias {} + | ------------------------- first implementation here +LL | impl OtherTrait for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias` + | + = note: upstream crates may add a new impl of trait `coherence_cross_crate_trait_decl::SomeTrait` for type `i32` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/coherence_generalization.rs b/tests/ui/type-alias-impl-trait/coherence_generalization.rs new file mode 100644 index 000000000..5c9ad9498 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_generalization.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Opaque<T> = impl Sized; +fn foo<T>() -> Opaque<T> { + () +} + +impl<T, V> Trait for (T, V, V, u32) {} +impl<U, V> Trait for (Opaque<U>, V, i32, V) {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/collect_hidden_types.rs b/tests/ui/type-alias-impl-trait/collect_hidden_types.rs new file mode 100644 index 000000000..e78f178e4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/collect_hidden_types.rs @@ -0,0 +1,22 @@ +// aux-build:collect_hidden_types.rs +use collect_hidden_types::Service; +use std::future::Future; +use std::pin::Pin; +use std::task::Context; + +// build-pass + +// edition:2018 + +extern crate collect_hidden_types; + +fn broken(mut a: collect_hidden_types::A, cx: &mut Context<'_>) { + let mut fut = a.call(()); + let _ = unsafe { Pin::new_unchecked(&mut fut) }.poll(cx); +} + +pub async fn meeb(cx: &mut Context<'_>) { + broken(collect_hidden_types::A, cx); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.rs b/tests/ui/type-alias-impl-trait/constrain_inputs.rs new file mode 100644 index 000000000..03fb64b7b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +mod lifetime_params { + type Ty<'a> = impl Sized; + fn defining(s: &str) -> Ty<'_> { s } + fn execute(ty: Ty<'_>) -> &str { todo!() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + + type BadFnSig = fn(Ty<'_>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime +} + +mod lifetime_params_2 { + type Ty<'a> = impl FnOnce() -> &'a str; + fn defining(s: &str) -> Ty<'_> { move || s } + fn execute(ty: Ty<'_>) -> &str { ty() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types +} + +// regression test for https://github.com/rust-lang/rust/issues/97104 +mod type_params { + type Ty<T> = impl Sized; + fn define<T>(s: T) -> Ty<T> { s } + + type BadFnSig = fn(Ty<&str>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr new file mode 100644 index 000000000..93953fd06 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -0,0 +1,58 @@ +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:6:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:9:35 + | +LL | type BadFnSig = fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:11:42 + | +LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:18:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { ty() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:27:37 + | +LL | type BadFnSig = fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:29:44 + | +LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0581, E0582. +For more information about an error, try `rustc --explain E0581`. diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs new file mode 100644 index 000000000..3bae0f173 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Static: 'static {} +impl Static for () {} + +type Gal<T> = impl Static; +fn _defining<T>() -> Gal<T> {} + +trait Callable<Arg> { type Output; } + +/// We can infer `<C as Callable<Arg>>::Output: 'static`, +/// because we know `C: 'static` and `Arg: 'static`, +fn box_str<C, Arg>(s: C::Output) -> Box<dyn AsRef<str> + 'static> +where + Arg: Static, + C: ?Sized + Callable<Arg> + 'static, + C::Output: AsRef<str>, +{ + Box::new(s) +} + +fn extend_lifetime(s: &str) -> Box<dyn AsRef<str> + 'static> { + type MalformedTy = dyn for<'a> Callable<Gal<&'a ()>, Output = &'a str>; + //~^ ERROR binding for associated type `Output` references lifetime `'a` + box_str::<MalformedTy, _>(s) +} + +fn main() { + let extended = extend_lifetime(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr new file mode 100644 index 000000000..d5fc46cb1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/constrain_inputs_unsound.rs:23:58 + | +LL | type MalformedTy = dyn for<'a> Callable<Gal<&'a ()>, Output = &'a str>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/type-alias-impl-trait/cross_crate_ice.rs b/tests/ui/type-alias-impl-trait/cross_crate_ice.rs new file mode 100644 index 000000000..c30608176 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_crate_ice.rs @@ -0,0 +1,16 @@ +// aux-build:cross_crate_ice.rs +// build-pass (FIXME(62277): could be check-pass?) + +extern crate cross_crate_ice; + +struct Bar(cross_crate_ice::Foo); + +impl Bar { + fn zero(&self) -> &cross_crate_ice::Foo { + &self.0 + } +} + +fn main() { + let _ = cross_crate_ice::foo(); +} diff --git a/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs b/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs new file mode 100644 index 000000000..3a7e49026 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs @@ -0,0 +1,11 @@ +// aux-build:cross_crate_ice2.rs +// build-pass (FIXME(62277): could be check-pass?) + +extern crate cross_crate_ice2; + +use cross_crate_ice2::View; + +fn main() { + let v = cross_crate_ice2::X; + v.test(); +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference.rs b/tests/ui/type-alias-impl-trait/cross_inference.rs new file mode 100644 index 000000000..dafaf40a6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let x: (_, _) = foo; + println!("{:?}", x); +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs new file mode 100644 index 000000000..9a50c0f98 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition=2021 +// check-pass +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let (a, b): (u32, u32) = foo; +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs new file mode 100644 index 000000000..b929122a6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2021 --crate-type=lib +// rustc-env:RUST_BACKTRACE=0 +// check-pass + +// tracked in https://github.com/rust-lang/rust/issues/96572 + +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let (a, b) = foo; // this line used to make the code fail +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs b/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs new file mode 100644 index 000000000..f6affbf17 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs @@ -0,0 +1,14 @@ +// check-pass + +fn foo(b: bool) -> impl Copy { + if b { + return (5,6) + } + let x: (_, _) = foo(true); + println!("{:?}", x); + (1u32, 2u32) +} + +fn main() { + foo(false); +} diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs b/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs new file mode 100644 index 000000000..6febd0715 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs @@ -0,0 +1,6 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// declared but never defined +type Bar = impl std::fmt::Debug; //~ ERROR unconstrained opaque type diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr new file mode 100644 index 000000000..60bc24320 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/declared_but_never_defined.rs:6:12 + | +LL | type Bar = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs new file mode 100644 index 000000000..5bda5f0fc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +mod boo { + // declared in module but not defined inside of it + pub type Boo = impl ::std::fmt::Debug; //~ ERROR unconstrained opaque type +} + +fn bomp() -> boo::Boo { + "" + //~^ mismatched types +} diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr new file mode 100644 index 000000000..fbfa0ccf1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -0,0 +1,25 @@ +error: unconstrained opaque type + --> $DIR/declared_but_not_defined_in_scope.rs:7:20 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Boo` must be used in combination with a concrete type within the same module + +error[E0308]: mismatched types + --> $DIR/declared_but_not_defined_in_scope.rs:11:5 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the expected opaque type +... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type +LL | "" + | ^^ expected opaque type, found `&str` + | + = note: expected opaque type `Boo` + found reference `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs new file mode 100644 index 000000000..8b51f5571 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// test that the type alias impl trait defining use is in a submodule + +fn main() {} + +type Foo = impl std::fmt::Display; +type Bar = impl std::fmt::Display; + +mod foo { + pub fn foo() -> super::Foo { + "foo" + } + + pub mod bar { + pub fn bar() -> crate::Bar { + 1 + } + } +} diff --git a/tests/ui/type-alias-impl-trait/destructuring.rs b/tests/ui/type-alias-impl-trait/destructuring.rs new file mode 100644 index 000000000..b752e5838 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructuring.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +// issue: https://github.com/rust-lang/rust/issues/104551 + +fn main() { + type T = impl Sized; + let (_a, _b): T = (1u32, 2u32); +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_defining_uses.rs new file mode 100644 index 000000000..4505c4d95 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar() -> Foo { + 42i32 + //~^ ERROR concrete type differs from previous +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr new file mode 100644 index 000000000..a8b4cd7af --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses.rs:13:5 + | +LL | 42i32 + | ^^^^^ expected `&'static str`, got `i32` + | +note: previous use here + --> $DIR/different_defining_uses.rs:9:5 + | +LL | "" + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs new file mode 100644 index 000000000..0b8157fe3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar() -> Foo { //~ ERROR: concrete type differs from previous defining opaque type use + panic!() +} + +fn boo() -> Foo { + loop {} +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr new file mode 100644 index 000000000..09dadb0af --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses_never_type.rs:12:13 + | +LL | fn bar() -> Foo { + | ^^^ expected `&'static str`, got `()` + | +note: previous use here + --> $DIR/different_defining_uses_never_type.rs:9:5 + | +LL | "" + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs new file mode 100644 index 000000000..8549687ea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs @@ -0,0 +1,44 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar(arg: bool) -> Foo { + if arg { + panic!() + } else { + "bar" + } +} + +fn boo(arg: bool) -> Foo { + if arg { + loop {} + } else { + "boo" + } +} + +fn bar2(arg: bool) -> Foo { + if arg { + "bar2" + } else { + panic!() + } +} + +fn boo2(arg: bool) -> Foo { + if arg { + "boo2" + } else { + loop {} + } +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs new file mode 100644 index 000000000..bc827a8f2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +type Tait = impl Sized; + +struct One; +fn one() -> Tait { One } + +struct Two<T>(T); +fn two() -> Tait { Two::<()>(todo!()) } +//~^ ERROR concrete type differs from previous defining opaque type use + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr new file mode 100644 index 000000000..146a57cbb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses_never_type3.rs:9:13 + | +LL | fn two() -> Tait { Two::<()>(todo!()) } + | ^^^^ expected `One`, got `Two<()>` + | +note: previous use here + --> $DIR/different_defining_uses_never_type3.rs:6:20 + | +LL | fn one() -> Tait { One } + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs new file mode 100644 index 000000000..5f75fdc71 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type OneLifetime<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { + a +} + +fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { + b + //~^ ERROR: concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr new file mode 100644 index 000000000..546598e8a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_lifetimes_defining_uses.rs:15:5 + | +LL | b + | ^ expected `&'a u32`, got `&'b u32` + | +note: previous use here + --> $DIR/different_lifetimes_defining_uses.rs:11:5 + | +LL | a + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/fallback.rs b/tests/ui/type-alias-impl-trait/fallback.rs new file mode 100644 index 000000000..d8cf7d71f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/fallback.rs @@ -0,0 +1,28 @@ +// Tests that we correctly handle opaque types being used opaquely, +// even within their defining scope. +// +#![feature(type_alias_impl_trait)] + +type Foo = impl Copy; + +enum Wrapper<T> { + First(T), + Second +} + +// This method constrains `Foo` to be `bool` +fn constrained_foo() -> Foo { + true +} + + +// This method does not constrain `Foo`. +// Per RFC 2071, function bodies may either +// fully constrain an opaque type, or place no +// constraints on it. +fn unconstrained_foo() -> Wrapper<Foo> { + Wrapper::Second + //~^ ERROR: type annotations needed +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr new file mode 100644 index 000000000..e767bfdb0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/fallback.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed + --> $DIR/fallback.rs:24:5 + | +LL | fn unconstrained_foo() -> Wrapper<Foo> { + | ------------ type must be known at this point +LL | Wrapper::Second + | ^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Wrapper` + | + = note: cannot satisfy `_: Copy` +help: consider specifying the generic argument + | +LL | Wrapper::<T>::Second + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/field-types.rs b/tests/ui/type-alias-impl-trait/field-types.rs new file mode 100644 index 000000000..d99ed5812 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/field-types.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// check-pass + +use std::fmt::Debug; + +type Foo = impl Debug; + +struct Bar { + foo: Foo, +} + +fn bar() -> Bar { + Bar { foo: "foo" } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/future.rs b/tests/ui/type-alias-impl-trait/future.rs new file mode 100644 index 000000000..56323216e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/future.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 +// compile-flags: --crate-type=lib + +use std::future::Future; + +trait Bar { + fn bar(&self); +} + +type FooFuture<B> = impl Future<Output = ()>; + +fn foo<B: Bar>(bar: B) -> FooFuture<B> { + async move { bar.bar() } + //~^ ERROR: the trait bound `B: Bar` is not satisfied +} + +pub fn mainish(ctx: &mut std::task::Context) { + let boom: FooFuture<u32> = unsafe { core::mem::zeroed() }; + Box::pin(boom).as_mut().poll(ctx); +} diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr new file mode 100644 index 000000000..7e76c120a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/future.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/future.rs:15:5 + | +LL | async move { bar.bar() } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `foo` + --> $DIR/future.rs:14:11 + | +LL | fn foo<B: Bar>(bar: B) -> FooFuture<B> { + | ^^^ required by this bound in `foo` +help: consider restricting type parameter `B` + | +LL | type FooFuture<B: Bar> = impl Future<Output = ()>; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs new file mode 100644 index 000000000..8b683ad28 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type MyIter<T> = impl Iterator<Item = T>; + +fn my_iter<T>(t: T) -> MyIter<T> { + std::iter::once(t) +} + +fn my_iter2<T>(t: T) -> MyIter<T> { + Some(t).into_iter() + //~^ ERROR concrete type differs from previous +} diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr new file mode 100644 index 000000000..47ac33462 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_different_defining_uses.rs:12:5 + | +LL | Some(t).into_iter() + | ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>` + | +note: previous use here + --> $DIR/generic_different_defining_uses.rs:8:5 + | +LL | std::iter::once(t) + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs new file mode 100644 index 000000000..9d938a616 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn one<'a>(t: &'a ()) -> Two<'a, 'a> { + t + //~^ ERROR non-defining opaque type use +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr new file mode 100644 index 000000000..72e1ef4b4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_lifetime_param.rs:12:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_lifetime_param.rs:9:10 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + | ^^ ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs new file mode 100644 index 000000000..80462f8ac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type TwoTys<T, U> = impl Debug; + + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; + +type TwoConsts<const X: usize, const Y: usize> = impl Debug; + + +fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> { + t + //~^ ERROR non-defining opaque type use in defining scope +} + +fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { + t + //~^ ERROR non-defining opaque type use in defining scope +} + +fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> { + t + //~^ ERROR non-defining opaque type use in defining scope +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr new file mode 100644 index 000000000..98e4bfea1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -0,0 +1,38 @@ +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:21:5 + | +LL | t + | ^ + | +note: type used multiple times + --> $DIR/generic_duplicate_param_use.rs:8:13 + | +LL | type TwoTys<T, U> = impl Debug; + | ^ ^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:26:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_param_use.rs:15:19 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:31:5 + | +LL | t + | ^ + | +note: constant used multiple times + --> $DIR/generic_duplicate_param_use.rs:17:16 + | +LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug; + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs new file mode 100644 index 000000000..c17d595db --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two<T: Debug, U> = impl Debug; + +fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> { + (t, 4u32) +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs new file mode 100644 index 000000000..201535efe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two<T, U> = impl Debug; + +fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { + t + //~^ ERROR `T` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr new file mode 100644 index 000000000..3dbfff745 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -0,0 +1,14 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use2.rs:11:5 + | +LL | t + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs new file mode 100644 index 000000000..e7a25fc72 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two<T, U> = impl Debug; + +fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { + t + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { + u + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr new file mode 100644 index 000000000..7bec38220 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -0,0 +1,25 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use3.rs:11:5 + | +LL | t + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use3.rs:16:5 + | +LL | u + | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs new file mode 100644 index 000000000..d1e5a0f01 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two<T, U> = impl Debug; + +fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { + u + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr new file mode 100644 index 000000000..21a5369d9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -0,0 +1,14 @@ +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use4.rs:11:5 + | +LL | u + | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs new file mode 100644 index 000000000..3bd1dda63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two<T, U> = impl Debug; + +fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, u) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} + +fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (u, t) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr new file mode 100644 index 000000000..586ea8234 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -0,0 +1,51 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:11:5 + | +LL | (t, u) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, U)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:11:5 + | +LL | (t, u) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, U)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:17:5 + | +LL | (u, t) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:17:5 + | +LL | (u, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs new file mode 100644 index 000000000..5120925e5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two<T, U> = impl Debug; + +fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, t) + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (u, t) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr new file mode 100644 index 000000000..cb162d382 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -0,0 +1,39 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:11:5 + | +LL | (t, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:16:5 + | +LL | (u, t) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:16:5 + | +LL | (u, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs new file mode 100644 index 000000000..feebf81ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two<A: Debug, B> = impl Debug; + +fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> { + (t, t) +} + +fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> { + (t, t2) +} + +fn four<T: Debug, U, V>(t: T, t2: T, u: U, v: V) -> Two<T, U> { + (t, t2) +} + +fn five<X, Y: Debug>(x: X, y: Y, y2: Y) -> Two<Y, X> { + (y, y2) +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs new file mode 100644 index 000000000..3a4b5047b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two<T, U> = impl Debug; + +fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> { + (t, 4u32) + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> { + (u, 4u32) + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr new file mode 100644 index 000000000..14cbfb380 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -0,0 +1,27 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:10:5 + | +LL | (t, 4u32) + | ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, u32)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:15:5 + | +LL | (u, 4u32) + | ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, u32)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs new file mode 100644 index 000000000..6afcdfe4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two<A, B> = impl Debug; + +trait Foo { + type Bar: Debug; + const BAR: Self::Bar; +} + +fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, u, T::BAR) + //~^ ERROR the trait bound `A: Foo` is not satisfied + //~| ERROR `A` doesn't implement `Debug` + //~| ERROR `B` doesn't implement `Debug` +} + +fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, u, 42) + //~^ ERROR `A` doesn't implement `Debug` + //~| ERROR `B` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr new file mode 100644 index 000000000..722693e42 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -0,0 +1,62 @@ +error[E0277]: the trait bound `A: Foo` is not satisfied + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | +help: consider restricting type parameter `A` + | +LL | type Two<A: Foo, B> = impl Debug; + | +++++ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, _)` to implement `Debug` +help: consider restricting type parameter `A` + | +LL | type Two<A: std::fmt::Debug, B> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, _)` to implement `Debug` +help: consider restricting type parameter `B` + | +LL | type Two<A, B: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:22:5 + | +LL | (t, u, 42) + | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, i32)` to implement `Debug` +help: consider restricting type parameter `A` + | +LL | type Two<A: std::fmt::Debug, B> = impl Debug; + | +++++++++++++++++ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:22:5 + | +LL | (t, u, 42) + | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, i32)` to implement `Debug` +help: consider restricting type parameter `B` + | +LL | type Two<A, B: std::fmt::Debug> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs new file mode 100644 index 000000000..106efefba --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Region<'a> = impl std::fmt::Debug + 'a; + + +fn region<'b>(a: &'b ()) -> Region<'b> { + a +} diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs new file mode 100644 index 000000000..f5045d382 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type OneTy<T> = impl Debug; + +type OneLifetime<'a> = impl Debug; + +type OneConst<const X: usize> = impl Debug; + +// Not defining uses, because they doesn't define *all* possible generics. + +fn concrete_ty() -> OneTy<u32> { + 5u32 + //~^ ERROR expected generic type parameter, found `u32` +} + +fn concrete_lifetime() -> OneLifetime<'static> { + 6u32 + //~^ ERROR non-defining opaque type use in defining scope +} + +fn concrete_const() -> OneConst<{ 123 }> { + 7u32 + //~^ ERROR expected generic constant parameter, found `123` +} diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr new file mode 100644 index 000000000..564648630 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -0,0 +1,30 @@ +error[E0792]: expected generic type parameter, found `u32` + --> $DIR/generic_nondefining_use.rs:16:5 + | +LL | type OneTy<T> = impl Debug; + | - this generic parameter must be used with a generic type parameter +... +LL | 5u32 + | ^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:21:5 + | +LL | type OneLifetime<'a> = impl Debug; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | 6u32 + | ^^^^ + +error[E0792]: expected generic constant parameter, found `123` + --> $DIR/generic_nondefining_use.rs:26:5 + | +LL | type OneConst<const X: usize> = impl Debug; + | -------------- this generic parameter must be used with a generic constant parameter +... +LL | 7u32 + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.rs b/tests/ui/type-alias-impl-trait/generic_not_used.rs new file mode 100644 index 000000000..c70f473cf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_not_used.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type WrongGeneric<T: 'static> = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> { + v + //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list +} diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.stderr b/tests/ui/type-alias-impl-trait/generic_not_used.stderr new file mode 100644 index 000000000..fd720239a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_not_used.stderr @@ -0,0 +1,14 @@ +error: at least one trait must be specified + --> $DIR/generic_not_used.rs:5:33 + | +LL | type WrongGeneric<T: 'static> = impl 'static; + | ^^^^^^^^^^^^ + +error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/generic_not_used.rs:9:5 + | +LL | v + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs new file mode 100644 index 000000000..d3e169a70 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +fn main() { + let y = 42; + let x = wrong_generic(&y); + let z: i32 = x; + //~^ ERROR expected generic type parameter, found `&'static i32 +} + +type WrongGeneric<T> = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn wrong_generic<T>(t: T) -> WrongGeneric<T> { + t + //~^ ERROR the parameter type `T` may not live long enough +} diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr new file mode 100644 index 000000000..19115fd28 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -0,0 +1,30 @@ +error: at least one trait must be specified + --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + | +LL | type WrongGeneric<T> = impl 'static; + | ^^^^^^^^^^^^ + +error[E0792]: expected generic type parameter, found `&'static i32` + --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + | +LL | let z: i32 = x; + | ^ +... +LL | type WrongGeneric<T> = impl 'static; + | - this generic parameter must be used with a generic type parameter + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + | +LL | t + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> { + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0310, E0792. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs new file mode 100644 index 000000000..d87a25aad --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait Trait {} +type Underconstrained<T: Trait> = impl Send; + +// no `Trait` bound +fn underconstrain<T>(_: T) -> Underconstrained<T> { + //~^ ERROR the trait bound `T: Trait` + unimplemented!() +} diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr new file mode 100644 index 000000000..c73288329 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/generic_underconstrained.rs:9:31 + | +LL | fn underconstrain<T>(_: T) -> Underconstrained<T> { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `Underconstrained` + --> $DIR/generic_underconstrained.rs:6:26 + | +LL | type Underconstrained<T: Trait> = impl Send; + | ^^^^^ required by this bound in `Underconstrained` +help: consider restricting type parameter `T` + | +LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs new file mode 100644 index 000000000..8adc0bf32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Underconstrained<T: std::fmt::Debug> = impl Send; + +// not a defining use, because it doesn't define *all* possible generics +fn underconstrained<U>(_: U) -> Underconstrained<U> { + //~^ ERROR `U` doesn't implement `Debug` + 5u32 +} + +type Underconstrained2<T: std::fmt::Debug> = impl Send; + +// not a defining use, because it doesn't define *all* possible generics +fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> { + //~^ ERROR `V` doesn't implement `Debug` + 5u32 +} diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr new file mode 100644 index 000000000..d77d978aa --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -0,0 +1,35 @@ +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_underconstrained2.rs:8:33 + | +LL | fn underconstrained<U>(_: U) -> Underconstrained<U> { + | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Underconstrained` + --> $DIR/generic_underconstrained2.rs:5:26 + | +LL | type Underconstrained<T: std::fmt::Debug> = impl Send; + | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained` +help: consider restricting type parameter `U` + | +LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> { + | +++++++++++++++++ + +error[E0277]: `V` doesn't implement `Debug` + --> $DIR/generic_underconstrained2.rs:16:43 + | +LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> { + | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Underconstrained2` + --> $DIR/generic_underconstrained2.rs:13:27 + | +LL | type Underconstrained2<T: std::fmt::Debug> = impl Send; + | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained2` +help: consider restricting type parameter `V` + | +LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> { + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs new file mode 100644 index 000000000..851c2f66c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs @@ -0,0 +1,17 @@ +// Ensure that we don't ICE if associated type impl trait is used in an impl +// with an unconstrained type parameter. + +#![feature(type_alias_impl_trait)] + +trait X { + type I; + fn f() -> Self::I; +} + +impl<T> X for () { + //~^ ERROR the type parameter `T` is not constrained + type I = impl Sized; + fn f() -> Self::I {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr new file mode 100644 index 000000000..8cf8fb1d1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-with-unconstrained-param.rs:11:6 + | +LL | impl<T> X for () { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs new file mode 100644 index 000000000..0efbd1c2b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +trait Foo { + type Assoc; +} + +impl Foo for i32 { + type Assoc = u32; +} +type ImplTrait = impl Sized; +fn constrain() -> ImplTrait { + 1u64 +} +impl Foo for i64 { + type Assoc = ImplTrait; +} + +trait Bar<T> {} + +impl<T: Foo> Bar<<T as Foo>::Assoc> for T {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs new file mode 100644 index 000000000..3f1a9d12b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +type Bar<T: Foo> = impl std::fmt::Debug; +fn defining_use<T: Foo>() -> Bar<T> { + 42 +} + +trait Bop {} + +impl Bop for Bar<()> {} + +// If the hidden type is the same, this is effectively a second impl for the same type. +impl Bop for Bar<i32> {} +//~^ ERROR conflicting implementations + +type Barr = impl std::fmt::Debug; +fn defining_use2() -> Barr { + 42 +} + +// Even completely different opaque types must conflict. +impl Bop for Barr {} +//~^ ERROR conflicting implementations + +// And obviously the hidden type must conflict, too. +impl Bop for i32 {} +//~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr new file mode 100644 index 000000000..aaf75cc3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -0,0 +1,30 @@ +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:17:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for Bar<i32> {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:26:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for Barr {} + | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:30:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for i32 {} + | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs new file mode 100644 index 000000000..9f32c5d88 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs @@ -0,0 +1,21 @@ +// compile-flags: --crate-type=lib +// check-pass + +#![feature(type_alias_impl_trait)] +type Alias = impl Sized; + +fn constrain() -> Alias { + 1i32 +} + +trait HideIt { + type Assoc; +} + +impl HideIt for () { + type Assoc = Alias; +} + +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs new file mode 100644 index 000000000..8ec20acef --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; +pub trait Yay { } +impl Yay for Foo { } + +fn foo() { + is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied + is_debug::<u32>(); // OK + is_yay::<Foo>(); // OK + is_debug::<Foo>(); // OK +} + +fn is_yay<T: Yay>() { } +fn is_debug<T: Debug>() { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr new file mode 100644 index 000000000..1c83105a1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `u32: Yay` is not satisfied + --> $DIR/impl_trait_for_tait_bound.rs:10:14 + | +LL | is_yay::<u32>(); + | ^^^ the trait `Yay` is not implemented for `u32` + | + = help: the trait `Yay` is implemented for `Foo` +note: required by a bound in `is_yay` + --> $DIR/impl_trait_for_tait_bound.rs:16:14 + | +LL | fn is_yay<T: Yay>() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs new file mode 100644 index 000000000..a4b8c2d19 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; + +pub trait Yay { } +impl Yay for u32 { } + +fn foo() { + is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied +} + +fn is_yay<T: Yay>() { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr new file mode 100644 index 000000000..a6440f02c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `Foo: Yay` is not satisfied + --> $DIR/impl_trait_for_tait_bound2.rs:11:14 + | +LL | is_yay::<Foo>(); + | ^^^ the trait `Yay` is not implemented for `Foo` + | + = help: the trait `Yay` is implemented for `u32` +note: required by a bound in `is_yay` + --> $DIR/impl_trait_for_tait_bound2.rs:14:14 + | +LL | fn is_yay<T: Yay>() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.rs b/tests/ui/type-alias-impl-trait/implied_bounds.rs new file mode 100644 index 000000000..53cbf8d22 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<'a> = impl Equals<SelfType = ()>; +fn _defining_use<'a>() -> WithLifetime<'a> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<'a>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<'a>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<'a>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl<S> Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.stderr b/tests/ui/type-alias-impl-trait/implied_bounds.stderr new file mode 100644 index 000000000..6f11b6663 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_bounds2.rs b/tests/ui/type-alias-impl-trait/implied_bounds2.rs new file mode 100644 index 000000000..b4c4c013c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds2.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type Ty<'a, A> = impl Sized + 'a; +fn defining<'a, A>() -> Ty<'a, A> {} +fn assert_static<T: 'static>() {} +fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds3.rs b/tests/ui/type-alias-impl-trait/implied_bounds3.rs new file mode 100644 index 000000000..e39c61328 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds3.rs @@ -0,0 +1,18 @@ +// check-pass + +fn foo<F>(_: F) +where + F: 'static, +{ +} + +fn from<F: Send>(f: F) -> impl Send { + f +} + +fn bar<T>() { + foo(from(|| ())) +} + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs b/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs new file mode 100644 index 000000000..4cf35f951 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs @@ -0,0 +1,31 @@ +trait StaticDefaultRef: 'static { + fn default_ref() -> &'static Self; +} + +impl StaticDefaultRef for str { + fn default_ref() -> &'static str { + "" + } +} + +fn into_impl(x: &str) -> &(impl ?Sized + AsRef<str> + StaticDefaultRef + '_) { + x +} + +fn extend_lifetime<'a>(x: &'a str) -> &'static str { + let t = into_impl(x); + helper(|_| t) //~ ERROR lifetime may not live long enough +} + +fn helper<T: ?Sized + AsRef<str> + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str { + f(T::default_ref()).as_ref() +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr new file mode 100644 index 000000000..151564c3b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_closure.rs:17:16 + | +LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str { + | -- lifetime `'a` defined here +LL | let t = into_impl(x); +LL | helper(|_| t) + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs new file mode 100644 index 000000000..8023cd24f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<T> = impl Equals<SelfType = ()>; +fn _defining_use<T>() -> WithLifetime<T> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<&'a ()>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<&'a ()>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl<S> Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr new file mode 100644 index 000000000..cbc5e6073 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_from_types.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs new file mode 100644 index 000000000..b6a7264a5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] + +// known-bug: #99840 +// this should not compile +// check-pass + +type Alias = impl Sized; + +fn constrain() -> Alias { + 1i32 +} + +trait HideIt { + type Assoc; +} + +impl HideIt for () { + type Assoc = Alias; +} + +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} +// impl Yay for i32 {} // this already errors +// impl Yay for u32 {} // this also already errors + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs new file mode 100644 index 000000000..07f825aea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs @@ -0,0 +1,43 @@ +#![feature(type_alias_impl_trait)] + +mod test_lifetime_param { + type Ty<'a> = impl Sized + 'a; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param { + type Ty<'a> = impl Sized + 'a; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param2 { + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_type_param { + type Ty<A> = impl Sized; + fn defining<A>(s: A) -> Ty<A> { s } + fn assert_static<A: 'static>() {} + fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + //~^ ERROR: parameter type `A` may not live long enough +} + +mod test_implied_from_fn_sig { + type Opaque<T: 'static> = impl Sized; + fn defining<T: 'static>() -> Opaque<T> {} + fn assert_static<T: 'static>() {} + fn test<T>(_: Opaque<T>) { assert_static::<T>(); } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr new file mode 100644 index 000000000..887620a4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -0,0 +1,58 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:6:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:15:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:22:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:8:43 + | +LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:17:46 + | +LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:24:21 + | +LL | fn test<'a>() { assert_static::<'a>() } + | -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:32:41 + | +LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() } + | +++++++++ + +error: aborting due to 4 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs new file mode 100644 index 000000000..ac32dbde0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +mod test_type_param_static { + type Ty<A> = impl Sized + 'static; + //~^ ERROR: the parameter type `A` may not live long enough + fn defining<A: 'static>(s: A) -> Ty<A> { s } + fn assert_static<A: 'static>() {} + fn test<A>() where Ty<A>: 'static { assert_static::<A>() } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr new file mode 100644 index 000000000..47bc31e78 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:4:18 + | +LL | type Ty<A> = impl Sized + 'static; + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | type Ty<A: 'static> = impl Sized + 'static; + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs new file mode 100644 index 000000000..ee9bce15d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Callable { + type Output; + fn call() -> Self::Output; +} + +impl<'a> Callable for &'a () { + type Output = impl Sized; + fn call() -> Self::Output {} +} + +fn test<'a>() -> impl Sized { + <&'a () as Callable>::call() +} + +fn want_static<T: 'static>(_: T) {} + +fn test2<'a>() { + want_static(<&'a () as Callable>::call()); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs new file mode 100644 index 000000000..ae21a9134 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs @@ -0,0 +1,38 @@ +#![feature(type_alias_impl_trait)] + +trait Callable { + type Output; + fn call(x: Self) -> Self::Output; +} + +trait PlusOne { + fn plus_one(&mut self); +} + +impl<'a> PlusOne for &'a mut i32 { + fn plus_one(&mut self) { + **self += 1; + } +} + +impl<T: PlusOne> Callable for T { + type Output = impl PlusOne; + fn call(t: T) -> Self::Output { t } +} + +fn test<'a>(y: &'a mut i32) -> impl PlusOne { + <&'a mut i32 as Callable>::call(y) + //~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds +} + +fn main() { + let mut z = 42; + let mut thing = test(&mut z); + let mut thing2 = test(&mut z); + thing.plus_one(); + assert_eq!(z, 43); + thing2.plus_one(); + assert_eq!(z, 44); + thing.plus_one(); + assert_eq!(z, 45); +} diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr new file mode 100644 index 000000000..0ed8a703b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds + --> $DIR/imply_bounds_from_bounds_param.rs:24:5 + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { + | -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here +LL | <&'a mut i32 as Callable>::call(y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs new file mode 100644 index 000000000..685d76ee3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs @@ -0,0 +1,15 @@ +// Regression test for issue 67856 + +#![feature(unboxed_closures)] +#![feature(type_alias_impl_trait)] +#![feature(fn_traits)] + +trait MyTrait {} +impl MyTrait for () {} + +impl<F> FnOnce<()> for &F { + //~^ ERROR type parameter `F` must be used + type Output = impl MyTrait; + extern "rust-call" fn call_once(self, _: ()) -> Self::Output {} +} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr new file mode 100644 index 000000000..b93ea955c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`) + --> $DIR/incoherent-assoc-imp-trait.rs:10:6 + | +LL | impl<F> FnOnce<()> for &F { + | ^ type parameter `F` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.rs b/tests/ui/type-alias-impl-trait/incomplete-inference.rs new file mode 100644 index 000000000..4c8bf2cfc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incomplete-inference.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Sized; + +fn bar() -> Foo { + None + //~^ ERROR: type annotations needed [E0282] +} + +fn baz() -> Foo { + Some(()) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr new file mode 100644 index 000000000..9a0e71b4e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-inference.rs:6:5 + | +LL | None + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None::<T> + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs new file mode 100644 index 000000000..79caddf79 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + type Foo = impl std::fmt::Debug; + //~^ ERROR cycle detected + + // Cycle: error today, but it'd be nice if it eventually worked + + pub fn foo() -> Foo { + is_send(bar()) + } + + pub fn bar() { + is_send(foo()); // Today: error + } + + fn baz() { + let f: Foo = 22_u32; + } + + fn is_send<T: Send>(_: T) {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr new file mode 100644 index 000000000..b9d646b92 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -0,0 +1,22 @@ +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:15:9 + | +LL | is_send(foo()); // Today: error + | ^^^^^^^ + = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-101750.rs b/tests/ui/type-alias-impl-trait/issue-101750.rs new file mode 100644 index 000000000..f564f4fa7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-101750.rs @@ -0,0 +1,37 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Trait {} + +type TAIT = impl Trait; + +struct Concrete; +impl Trait for Concrete {} + +fn tait() -> TAIT { + Concrete +} + +trait OuterTrait { + type Item; +} +struct Dummy<T> { + t: T, +} +impl<T> OuterTrait for Dummy<T> { + type Item = T; +} + +fn tait_and_impl_trait() -> impl OuterTrait<Item = (TAIT, impl Trait)> { + Dummy { + t: (tait(), Concrete), + } +} + +fn tait_and_dyn_trait() -> impl OuterTrait<Item = (TAIT, Box<dyn Trait>)> { + let b: Box<dyn Trait> = Box::new(Concrete); + Dummy { t: (tait(), b) } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs new file mode 100644 index 000000000..0d3bace4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![cfg_attr(specialized, feature(specialization))] +#![allow(incomplete_features)] + +// revisions: stock specialized +// [specialized]check-pass + +trait OpaqueTrait {} +impl<T> OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + || 0 +} +trait AnotherTrait {} +impl<T: Send> AnotherTrait for T {} +impl AnotherTrait for OpaqueType {} +//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr new file mode 100644 index 000000000..47bae8bd1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + --> $DIR/issue-104817.rs:16:1 + | +LL | impl<T: Send> AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs new file mode 100644 index 000000000..50eeff0b1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs @@ -0,0 +1,13 @@ +// Checks to ensure that we properly detect when a closure constrains an opaque type + +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() { + type Opaque = impl Debug; + fn _unused() -> Opaque { String::new() } + let null = || -> Opaque { 0 }; + //~^ ERROR: concrete type differs from previous defining opaque type use + println!("{:?}", null()); +} diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr new file mode 100644 index 000000000..4c5fd2255 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-52843-closure-constrain.rs:10:31 + | +LL | let null = || -> Opaque { 0 }; + | ^ expected `String`, got `i32` + | +note: previous use here + --> $DIR/issue-52843-closure-constrain.rs:9:30 + | +LL | fn _unused() -> Opaque { String::new() } + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-52843.rs b/tests/ui/type-alias-impl-trait/issue-52843.rs new file mode 100644 index 000000000..159d3ccd2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +type Foo<T> = impl Default; + +#[allow(unused)] +fn foo<T: Default>(t: T) -> Foo<T> { + t + //~^ ERROR: the trait bound `T: Default` is not satisfied +} + +struct NotDefault; + +fn main() { + let _ = Foo::<NotDefault>::default(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr new file mode 100644 index 000000000..acd40f980 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Default` is not satisfied + --> $DIR/issue-52843.rs:7:5 + | +LL | t + | ^ the trait `Default` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type Foo<T: std::default::Default> = impl Default; + | +++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs new file mode 100644 index 000000000..057930f0c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Bug<T, U> = impl Fn(T) -> U + Copy; //~ ERROR cycle detected + +const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) }; + +fn make_bug<T, U: From<T>>() -> Bug<T, U> { + |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied +} + +fn main() { + CONST_BUG(0); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr new file mode 100644 index 000000000..2565a28b4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -0,0 +1,46 @@ +error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug<T, U> = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:6:1 + | +LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Bug<u8, ()>`... + = note: ...which requires normalizing `Bug<u8, ()>`... + = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/issue-53092-2.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | #![allow(dead_code)] +LL | | +LL | | type Bug<T, U> = impl Fn(T) -> U + Copy; +... | +LL | | CONST_BUG(0); +LL | | } + | |_^ + +error[E0277]: the trait bound `U: From<T>` is not satisfied + --> $DIR/issue-53092-2.rs:9:5 + | +LL | |x| x.into() + | ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U` + | +note: required by a bound in `make_bug` + --> $DIR/issue-53092-2.rs:8:19 + | +LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> { + | ^^^^^^^ required by this bound in `make_bug` +help: consider restricting type parameter `U` + | +LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy; + | +++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0391. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092.rs b/tests/ui/type-alias-impl-trait/issue-53092.rs new file mode 100644 index 000000000..1be5b46d6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Bug<T, U> = impl Fn(T) -> U + Copy; + +union Moo { + x: Bug<u8, ()>, + y: (), +} + +const CONST_BUG: Bug<u8, ()> = unsafe { Moo { y: () }.x }; + +fn make_bug<T, U: From<T>>() -> Bug<T, U> { + |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied +} + +fn main() { + CONST_BUG(0); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr new file mode 100644 index 000000000..2109cf8a7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: From<T>` is not satisfied + --> $DIR/issue-53092.rs:14:5 + | +LL | |x| x.into() + | ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U` + | +note: required by a bound in `make_bug` + --> $DIR/issue-53092.rs:13:19 + | +LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> { + | ^^^^^^^ required by this bound in `make_bug` +help: consider restricting type parameter `U` + | +LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy; + | +++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs new file mode 100644 index 000000000..007dcf3bc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53096.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> usize; +const fn bar() -> Foo { + || 0usize +} +const BAZR: Foo = bar(); + +#[rustc_error] +fn main() {} //~ ERROR diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr new file mode 100644 index 000000000..0af3a75f8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53096.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53096.rs:11:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs new file mode 100644 index 000000000..4a11bb502 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> Foo; + +fn foo() -> Foo { +//~^ ERROR: overflow evaluating the requirement + foo +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr new file mode 100644 index 000000000..0a34e8486 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -0,0 +1,12 @@ +error[E0275]: overflow evaluating the requirement `Foo: Sized` + --> $DIR/issue-53398-cyclic-types.rs:5:13 + | +LL | fn foo() -> Foo { + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) + = note: required because it appears within the type `fn() -> Foo {foo}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/issue-53598.rs b/tests/ui/type-alias-impl-trait/issue-53598.rs new file mode 100644 index 000000000..9c1cbf926 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53598.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +pub trait Foo { + type Item: Debug; + + fn foo<T: Debug>(_: T) -> Self::Item; +} + +#[derive(Debug)] +pub struct S<T>(std::marker::PhantomData<T>); + +pub struct S2; + +impl Foo for S2 { + type Item = impl Debug; + + fn foo<T: Debug>(_: T) -> Self::Item { + S::<T>(Default::default()) + //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() { + S2::foo(123); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53598.stderr b/tests/ui/type-alias-impl-trait/issue-53598.stderr new file mode 100644 index 000000000..f8b8201e2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53598.stderr @@ -0,0 +1,8 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-53598.rs:20:9 + | +LL | S::<T>(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs new file mode 100644 index 000000000..a3f126d56 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs @@ -0,0 +1,19 @@ +#![feature(generators, generator_trait, rustc_attrs)] +#![feature(type_alias_impl_trait)] + +use std::ops::Generator; + +type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>; + +const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> { + move || { + yield yielding; + + return returning; + } +} + +const FOO: GenOnce<usize, usize> = const_generator(10, 100); + +#[rustc_error] +fn main() {} //~ ERROR diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr new file mode 100644 index 000000000..eb1c9603a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53678-generator-and-const-fn.rs:19:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs new file mode 100644 index 000000000..af0780ab0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs @@ -0,0 +1,26 @@ +// check-pass +// Regression test for issue #55099 +// Tests that we don't incorrectly consider a lifetime to part +// of the concrete type + +#![feature(type_alias_impl_trait)] + +trait Future {} + +struct AndThen<F>(F); + +impl<F> Future for AndThen<F> {} + +struct Foo<'a> { + x: &'a mut (), +} + +type F = impl Future; + +impl<'a> Foo<'a> { + fn reply(&mut self) -> F { + AndThen(|| ()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs b/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs new file mode 100644 index 000000000..3a7a5da07 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs @@ -0,0 +1,24 @@ +// Regression test for #57188 + +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Baz<'a> { + source: &'a str, +} + +trait Foo<'a> { + type T: Iterator<Item = Baz<'a>> + 'a; + fn foo(source: &'a str) -> Self::T; +} + +struct Bar; +impl<'a> Foo<'a> for Bar { + type T = impl Iterator<Item = Baz<'a>> + 'a; + fn foo(source: &'a str) -> Self::T { + std::iter::once(Baz { source }) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs new file mode 100644 index 000000000..cad3e0f66 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -0,0 +1,26 @@ +// check-pass +// Regression test for issue #57611 +// Ensures that we don't ICE + +#![feature(trait_alias)] +#![feature(type_alias_impl_trait)] + +trait Foo { + type Bar: Baz<Self, Self>; + + fn bar(&self) -> Self::Bar; +} + +struct X; + +impl Foo for X { + type Bar = impl Baz<Self, Self>; + + fn bar(&self) -> Self::Bar { + |x| x + } +} + +trait Baz<A: ?Sized, B: ?Sized> = Fn(&A) -> &B; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57700.rs b/tests/ui/type-alias-impl-trait/issue-57700.rs new file mode 100644 index 000000000..484589387 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57700.rs @@ -0,0 +1,21 @@ +#![feature(arbitrary_self_types)] +#![feature(type_alias_impl_trait)] + +use std::ops::Deref; + +trait Foo { + type Bar: Foo; + + fn foo(self: impl Deref<Target = Self>) -> Self::Bar; +} + +impl<C> Foo for C { + type Bar = impl Foo; + + fn foo(self: impl Deref<Target = Self>) -> Self::Bar { + self + //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57700.stderr b/tests/ui/type-alias-impl-trait/issue-57700.stderr new file mode 100644 index 000000000..31b6df5d4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57700.stderr @@ -0,0 +1,8 @@ +error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-57700.rs:16:9 + | +LL | self + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs b/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs new file mode 100644 index 000000000..fcab2c7db --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs @@ -0,0 +1,31 @@ +// Regression test for issue #57807 - ensure +// that we properly unify associated types within +// a type alias impl trait +// check-pass +#![feature(type_alias_impl_trait)] + +trait Bar { + type A; +} + +impl Bar for () { + type A = (); +} + +trait Foo { + type A; + type B: Bar<A = Self::A>; + + fn foo() -> Self::B; +} + +impl Foo for () { + type A = (); + type B = impl Bar<A = Self::A>; + + fn foo() -> Self::B { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs new file mode 100644 index 000000000..4aa5966ff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57961.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +type X = impl Sized; + +trait Foo { + type Bar: Iterator<Item = X>; +} + +impl Foo for () { + type Bar = std::vec::IntoIter<u32>; + //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32` +} + +fn incoherent() { + let f: X = 22_i32; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57961.stderr b/tests/ui/type-alias-impl-trait/issue-57961.stderr new file mode 100644 index 000000000..8d11b4888 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57961.stderr @@ -0,0 +1,20 @@ +error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32` + --> $DIR/issue-57961.rs:10:16 + | +LL | type X = impl Sized; + | ---------- the expected opaque type +... +LL | type Bar = std::vec::IntoIter<u32>; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `X` + found type `u32` +note: required by a bound in `Foo::Bar` + --> $DIR/issue-57961.rs:6:24 + | +LL | type Bar: Iterator<Item = X>; + | ^^^^^^^^ required by this bound in `Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs new file mode 100644 index 000000000..477b61390 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs @@ -0,0 +1,39 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +type RandGenerator<'a> = impl Generator<Return = (), Yield = u64> + 'a; +fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> { + move || { + let _rng = rng; + loop { + yield 0; + } + } +} + +pub type RandGeneratorWithIndirection<'c> = impl Generator<Return = (), Yield = u64> + 'c; +pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return = (), Yield = u64> { + move || { + let _rng = rng; + loop { + yield 0; + } + } + } + + helper(rng) +} + +fn main() { + let mut gen = rand_generator(&()); + match unsafe { Pin::new_unchecked(&mut gen) }.resume(()) { + GeneratorState::Yielded(_) => {} + GeneratorState::Complete(_) => {} + }; +} diff --git a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs new file mode 100644 index 000000000..27ca7d0fd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +trait Trait {} + +impl<T> Trait for T {} + +type Foo<'c> = impl Trait + 'c; +fn foo<'a>(rng: &'a ()) -> Foo<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Trait { + rng + } + + helper(rng) +} + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/issue-58887.rs b/tests/ui/type-alias-impl-trait/issue-58887.rs new file mode 100644 index 000000000..96ac78602 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58887.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +impl<I, T, E> UnwrapItemsExt for I +where + I: Iterator<Item = Result<T, E>>, + E: std::fmt::Debug, +{ + type Iter = impl Iterator<Item = T>; + + fn unwrap_items(self) -> Self::Iter { + self.map(|x| x.unwrap()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-58951-2.rs b/tests/ui/type-alias-impl-trait/issue-58951-2.rs new file mode 100644 index 000000000..e4ba7f8e2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58951-2.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +mod defining_use_scope { + pub type A = impl Iterator; + + pub fn def_a() -> A { + 0..1 + } +} +use defining_use_scope::*; + +pub fn use_a() { + def_a().map(|x| x); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-58951.rs b/tests/ui/type-alias-impl-trait/issue-58951.rs new file mode 100644 index 000000000..7303cbab4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58951.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type A = impl Iterator; + +fn def_a() -> A { + 0..1 +} + +pub fn use_a() { + def_a().map(|x| x); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60371.rs b/tests/ui/type-alias-impl-trait/issue-60371.rs new file mode 100644 index 000000000..9a40f3d9b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60371.rs @@ -0,0 +1,14 @@ +trait Bug { + type Item: Bug; + + const FUN: fn() -> Self::Item; +} + +impl Bug for &() { + type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable + + const FUN: fn() -> Self::Item = || (); + //~^ ERROR the trait bound `(): Bug` is not satisfied +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60371.stderr b/tests/ui/type-alias-impl-trait/issue-60371.stderr new file mode 100644 index 000000000..d0c04371b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60371.stderr @@ -0,0 +1,21 @@ +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/issue-60371.rs:8:17 + | +LL | type Item = impl Bug; + | ^^^^^^^^ + | + = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): Bug` is not satisfied + --> $DIR/issue-60371.rs:10:40 + | +LL | const FUN: fn() -> Self::Item = || (); + | ^^ the trait `Bug` is not implemented for `()` + | + = help: the trait `Bug` is implemented for `&()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs new file mode 100644 index 000000000..b833429c7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60407.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait, rustc_attrs)] + +type Debuggable = impl core::fmt::Debug; + +static mut TEST: Option<Debuggable> = None; + +#[rustc_error] +fn main() { + //~^ ERROR + unsafe { TEST = Some(foo()) } +} + +fn foo() -> Debuggable { + 0u32 +} diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr new file mode 100644 index 000000000..fecee2779 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60407.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-60407.rs:8:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-60564-working.rs b/tests/ui/type-alias-impl-trait/issue-60564-working.rs new file mode 100644 index 000000000..38accc824 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564-working.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait IterBits { + type BitsIter: Iterator<Item = u8>; + fn iter_bits(self, n: u8) -> Self::BitsIter; +} + +impl<T: Copy, E> IterBits for T +where + T: std::ops::Shr<Output = T> + + std::ops::BitAnd<T, Output = T> + + std::convert::From<u8> + + std::convert::TryInto<u8, Error = E>, + E: std::fmt::Debug, +{ + type BitsIter = impl std::iter::Iterator<Item = u8>; + fn iter_bits(self, n: u8) -> Self::BitsIter { + (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs new file mode 100644 index 000000000..c2f4c3708 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +trait IterBits { + type BitsIter: Iterator<Item = u8>; + fn iter_bits(self, n: u8) -> Self::BitsIter; +} + +type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; + +impl<T: Copy, E> IterBits for T +where + T: std::ops::Shr<Output = T> + + std::ops::BitAnd<T, Output = T> + + std::convert::From<u8> + + std::convert::TryInto<u8, Error = E>, + E: std::fmt::Debug, +{ + type BitsIter = IterBitsIter<T, E, u8>; + fn iter_bits(self, n: u8) -> Self::BitsIter { + (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + //~^ ERROR expected generic type parameter, found `u8` + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr new file mode 100644 index 000000000..f8fdb004d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `u8` + --> $DIR/issue-60564.rs:20:9 + | +LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; + | - this generic parameter must be used with a generic type parameter +... +LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-60662.rs b/tests/ui/type-alias-impl-trait/issue-60662.rs new file mode 100644 index 000000000..b9faa668b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60662.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Z unpretty=hir + +#![feature(type_alias_impl_trait)] + +trait Animal {} + +fn main() { + pub type ServeFut = impl Animal; +} diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout new file mode 100644 index 000000000..5b3d7375d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Z unpretty=hir + +#![feature(type_alias_impl_trait)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Animal { } + +fn main() { + type ServeFut = /*impl Trait*/; + } diff --git a/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs b/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs new file mode 100644 index 000000000..36779a0ce --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs @@ -0,0 +1,38 @@ +// Regression test for #62988 + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait MyTrait { + type AssocType: Send; + fn ret(&self) -> Self::AssocType; +} + +impl MyTrait for () { + type AssocType = impl Send; + fn ret(&self) -> Self::AssocType { + () + } +} + +impl<'a> MyTrait for &'a () { + type AssocType = impl Send; + fn ret(&self) -> Self::AssocType { + () + } +} + +trait MyLifetimeTrait<'a> { + type AssocType: Send + 'a; + fn ret(&self) -> Self::AssocType; +} + +impl<'a> MyLifetimeTrait<'a> for &'a () { + type AssocType = impl Send + 'a; + fn ret(&self) -> Self::AssocType { + *self + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs new file mode 100644 index 000000000..7414611a7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs @@ -0,0 +1,13 @@ +// Regression test for issue #63263. +// Tests that we properly handle closures with an explicit return type +// that return an opaque type. + +// check-pass + +#![feature(type_alias_impl_trait)] + +pub type Closure = impl FnOnce(); + +fn main() { + || -> Closure { || () }; +} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs new file mode 100644 index 000000000..97332e16d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63279.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zsave-analysis + +#![feature(type_alias_impl_trait)] + +type Closure = impl FnOnce(); + +fn c() -> Closure { + //~^ ERROR: expected a `FnOnce<()>` closure, found `()` + || -> Closure { || () } + //~^ ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: expected a `FnOnce<()>` closure, found `()` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr new file mode 100644 index 000000000..110b8d1ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -0,0 +1,48 @@ +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:7:11 + | +LL | fn c() -> Closure { + | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` + | + = help: the trait `FnOnce<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:9:11 + | +LL | || -> Closure { || () } + | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` + | + = help: the trait `FnOnce<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0308]: mismatched types + --> $DIR/issue-63279.rs:9:21 + | +LL | || -> Closure { || () } + | ^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:9:21: 9:23]` +help: use parentheses to call this closure + | +LL | || -> Closure { (|| ())() } + | + +++ + +error[E0308]: mismatched types + --> $DIR/issue-63279.rs:9:5 + | +LL | || -> Closure { || () } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:9:5: 9:18]` +help: use parentheses to call this closure + | +LL | (|| -> Closure { || () })() + | + +++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-63355.rs b/tests/ui/type-alias-impl-trait/issue-63355.rs new file mode 100644 index 000000000..7066a0535 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63355.rs @@ -0,0 +1,46 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +pub trait Foo {} + +pub trait Bar { + type Foo: Foo; + + fn foo() -> Self::Foo; +} + +pub trait Baz { + type Foo: Foo; + type Bar: Bar<Foo = Self::Foo>; + + fn foo() -> Self::Foo; + fn bar() -> Self::Bar; +} + +impl Foo for () {} + +impl Bar for () { + type Foo = FooImpl; + + fn foo() -> Self::Foo { + () + } +} + +pub type FooImpl = impl Foo; +pub type BarImpl = impl Bar<Foo = FooImpl>; + +impl Baz for () { + type Foo = FooImpl; + type Bar = BarImpl; + + fn foo() -> Self::Foo { + () + } + + fn bar() -> Self::Bar { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs new file mode 100644 index 000000000..28f4a85c9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs @@ -0,0 +1,21 @@ +// check-pass +// Regression test for issue #63677 - ensure that +// coherence checking can properly handle 'impl trait' +// in type aliases +#![feature(type_alias_impl_trait)] + +pub trait Trait {} +pub struct S1<T>(T); +pub struct S2<T>(T); + +pub type T1 = impl Trait; +pub type T2 = S1<T1>; +pub type T3 = S2<T2>; + +impl<T> Trait for S1<T> {} +impl<T: Trait> S2<T> {} +impl T3 {} + +pub fn use_t1() -> T1 { S1(()) } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.rs b/tests/ui/type-alias-impl-trait/issue-65384.rs new file mode 100644 index 000000000..9a9b2269f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65384.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +trait MyTrait {} + +impl MyTrait for () {} + +type Bar = impl MyTrait; + +impl MyTrait for Bar {} +//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()` + +fn bazr() -> Bar { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.stderr b/tests/ui/type-alias-impl-trait/issue-65384.stderr new file mode 100644 index 000000000..f6692ae32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65384.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `()` + --> $DIR/issue-65384.rs:10:1 + | +LL | impl MyTrait for () {} + | ------------------- first implementation here +... +LL | impl MyTrait for Bar {} + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 000000000..72c22827f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -0,0 +1,18 @@ +// compile-flags: -Zsave-analysis +// check-pass + +#![feature(type_alias_impl_trait, rustc_attrs)] + +type T = impl Sized; +// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed +// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; +// so difference assertion should not be declared on impl-trait-type-alias's instances. +// for details, check RFC-2515: +// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md + +fn take(_: fn() -> T) {} + +fn main() { + take(|| {}); + take(|| {}); +} diff --git a/tests/ui/type-alias-impl-trait/issue-65918.rs b/tests/ui/type-alias-impl-trait/issue-65918.rs new file mode 100644 index 000000000..af6d50109 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65918.rs @@ -0,0 +1,51 @@ +// ignore-test: This now ICEs again. + +// build-pass + +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +/* copied Index and TryFrom for convenience (and simplicity) */ +trait MyIndex<T> { + type O; + fn my_index(self) -> Self::O; +} +trait MyFrom<T>: Sized { + type Error; + fn my_from(value: T) -> Result<Self, Self::Error>; +} + +/* MCVE starts here */ +trait F {} +impl F for () {} +type DummyT<T> = impl F; +fn _dummy_t<T>() -> DummyT<T> {} + +struct Phantom1<T>(PhantomData<T>); +struct Phantom2<T>(PhantomData<T>); +struct Scope<T>(Phantom2<DummyT<T>>); + +impl<T> Scope<T> { + fn new() -> Self { + unimplemented!() + } +} + +impl<T> MyFrom<Phantom2<T>> for Phantom1<T> { + type Error = (); + fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> { + unimplemented!() + } +} + +impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> { + type O = T; + fn my_index(self) -> Self::O { + MyFrom::my_from(self.0).ok().unwrap() + } +} + +fn main() { + let _pos: Phantom1<DummyT<()>> = Scope::new().my_index(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs new file mode 100644 index 000000000..d97270c31 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs @@ -0,0 +1,21 @@ +// Regression test for issue #66580 +// Ensures that we don't try to determine whether a closure +// is foreign when it's the underlying type of an opaque type +// check-pass +#![feature(type_alias_impl_trait)] + +type Closure = impl FnOnce(); + +fn closure() -> Closure { + || {} +} + +struct Wrap<T> { + f: T, +} + +impl Wrap<Closure> {} + +impl<T> Wrap<T> {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs new file mode 100644 index 000000000..cd219328a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs @@ -0,0 +1,33 @@ +// check-pass +// Regression test for issue #67844 +// Ensures that we properly handle nested TAIT occurrences +// with generic parameters + +#![feature(type_alias_impl_trait)] + +trait WithAssoc { + type AssocType; +} + +trait WithParam<A> {} + +type Return<A> = impl WithAssoc<AssocType = impl WithParam<A>>; + +struct MyParam; +impl<A> WithParam<A> for MyParam {} + +struct MyStruct; + +impl WithAssoc for MyStruct { + type AssocType = MyParam; +} + +fn my_fun<A>() -> Return<A> { + MyStruct +} + +fn my_other_fn<A>() -> impl WithAssoc<AssocType = impl WithParam<A>> { + MyStruct +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs new file mode 100644 index 000000000..5e0a82a72 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -0,0 +1,14 @@ +// Regression test for issue #68368 +// Ensures that we don't ICE when emitting an error +// for a non-defining use when lifetimes are involved + +#![feature(type_alias_impl_trait)] +trait Trait<T> {} +type Alias<'a, U> = impl Trait<U>; + +fn f<'a>() -> Alias<'a, ()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} + +impl<X> Trait<X> for () {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr new file mode 100644 index 000000000..271743a40 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-68368-non-defining-use-2.rs:9:29 + | +LL | type Alias<'a, U> = impl Trait<U>; + | - this generic parameter must be used with a generic type parameter +LL | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs new file mode 100644 index 000000000..3b32260c9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -0,0 +1,14 @@ +// Regression test for issue #68368 +// Ensures that we don't ICE when emitting an error +// for a non-defining use when lifetimes are involved + +#![feature(type_alias_impl_trait)] +trait Trait<T> {} +type Alias<'a, U> = impl Trait<U>; + +fn f<'a>() -> Alias<'a, ()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} + +impl Trait<()> for () {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr new file mode 100644 index 000000000..4d9a8d6ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-68368-non-defining-use.rs:9:29 + | +LL | type Alias<'a, U> = impl Trait<U>; + | - this generic parameter must be used with a generic type parameter +LL | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs new file mode 100644 index 000000000..7657fe2fb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs @@ -0,0 +1,23 @@ +// Regression test for #69136 + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} + +impl SomeTrait for () {} + +trait WithAssoc<A> { + type AssocType; +} + +impl<T> WithAssoc<T> for () { + type AssocType = (); +} + +type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; +//~^ ERROR use of undeclared lifetime name `'a` + +fn my_fun() -> Return<()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr new file mode 100644 index 000000000..d1250786d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -0,0 +1,29 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65 + | +LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type Return<A> = impl for<'a> WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | +++ + +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 + | +LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | - this generic parameter must be used with a generic type parameter +... +LL | fn my_fun() -> Return<()> {} + | ^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0792. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs new file mode 100644 index 000000000..a6916eda8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs @@ -0,0 +1,23 @@ +// Test-pass variant of #69136 + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} + +impl SomeTrait for () {} + +trait WithAssoc { + type AssocType; +} + +impl WithAssoc for () { + type AssocType = (); +} + +type Return<'a> = impl WithAssoc<AssocType = impl Sized + 'a>; + +fn my_fun<'a>() -> Return<'a> {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69323.rs b/tests/ui/type-alias-impl-trait/issue-69323.rs new file mode 100644 index 000000000..a9bd6daf2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69323.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +use std::iter::{once, Chain}; + +fn test1<A: Iterator<Item = &'static str>>(x: A) -> Chain<A, impl Iterator<Item = &'static str>> { + x.chain(once(",")) +} + +type I<A> = Chain<A, impl Iterator<Item = &'static str>>; +fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> { + x.chain(once(",")) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs new file mode 100644 index 000000000..dff0d89d4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-70121.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub type Successors<'a> = impl Iterator<Item = &'a ()>; + +pub fn f<'a>() -> Successors<'a> { + None.into_iter() +} + +pub trait Tr { + type Item; +} + +impl<'a> Tr for &'a () { + type Item = Successors<'a>; +} + +pub fn kazusa<'a>() -> <&'a () as Tr>::Item { + None.into_iter() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-72793.rs b/tests/ui/type-alias-impl-trait/issue-72793.rs new file mode 100644 index 000000000..828c87114 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-72793.rs @@ -0,0 +1,25 @@ +// check-pass +// compile-flags: -Zmir-opt-level=3 + +#![feature(type_alias_impl_trait)] + +trait T { type Item; } + +type Alias<'a> = impl T<Item = &'a ()>; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs new file mode 100644 index 000000000..bb4104b3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74244.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +trait Allocator { + type Buffer; +} + +struct DefaultAllocator; + +impl<T> Allocator for DefaultAllocator { + //~^ ERROR: the type parameter `T` is not constrained + type Buffer = (); +} + +type A = impl Fn(<DefaultAllocator as Allocator>::Buffer); + +fn foo() -> A { + |_| () +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr new file mode 100644 index 000000000..ff6bacd27 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74244.rs:9:6 + | +LL | impl<T> Allocator for DefaultAllocator { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74280.rs b/tests/ui/type-alias-impl-trait/issue-74280.rs new file mode 100644 index 000000000..ad641eaa0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74280.rs @@ -0,0 +1,12 @@ +// Regression test for #74280. + +#![feature(type_alias_impl_trait)] + +type Test = impl Copy; + +fn test() -> Test { + let y = || -> Test { () }; + 7 //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74280.stderr b/tests/ui/type-alias-impl-trait/issue-74280.stderr new file mode 100644 index 000000000..66886db6e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74280.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-74280.rs:9:5 + | +LL | fn test() -> Test { + | ---- expected `()` because of return type +LL | let y = || -> Test { () }; +LL | 7 + | ^ expected `()`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.rs b/tests/ui/type-alias-impl-trait/issue-74761-2.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +pub trait A { + type B; + fn f(&self) -> Self::B; +} +impl<'a, 'b> A for () { + //~^ ERROR the lifetime parameter `'a` is not constrained + //~| ERROR the lifetime parameter `'b` is not constrained + type B = impl core::fmt::Debug; + + fn f(&self) -> Self::B {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr new file mode 100644 index 000000000..f15d0a069 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -0,0 +1,15 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:7:6 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:7:10 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761.rs b/tests/ui/type-alias-impl-trait/issue-74761.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +pub trait A { + type B; + fn f(&self) -> Self::B; +} +impl<'a, 'b> A for () { + //~^ ERROR the lifetime parameter `'a` is not constrained + //~| ERROR the lifetime parameter `'b` is not constrained + type B = impl core::fmt::Debug; + + fn f(&self) -> Self::B {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr new file mode 100644 index 000000000..1d016fe07 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr @@ -0,0 +1,15 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761.rs:7:6 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761.rs:7:10 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs new file mode 100644 index 000000000..b97e444c6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -0,0 +1,31 @@ +// Regression test for issue #76202 +// Tests that we don't ICE when we have a trait impl on a TAIT. + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Dummy {} +impl Dummy for () {} + +type F = impl Dummy; +fn f() -> F {} + +trait Test { + fn test(self); +} + +impl Test for F { + fn test(self) {} +} + +// Ok because `i32` does not implement `Dummy`, +// so it can't possibly be the hidden type of `F`. +impl Test for i32 { + fn test(self) {} +} + +fn main() { + let x: F = f(); + x.test(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs new file mode 100644 index 000000000..8d818d4a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -0,0 +1,14 @@ +// Regression test for #77179. + +#![feature(type_alias_impl_trait)] + +type Pointer<T> = impl std::ops::Deref<Target=T>; + +fn test() -> Pointer<_> { + //~^ ERROR: the placeholder `_` is not allowed within types + Box::new(1) +} + +fn main() { + test(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr new file mode 100644 index 000000000..053546e4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-77179.rs:7:22 + | +LL | fn test() -> Pointer<_> { + | --------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Pointer<i32>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/issue-78450.rs b/tests/ui/type-alias-impl-trait/issue-78450.rs new file mode 100644 index 000000000..fccbfb74f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-78450.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait AssociatedImpl { + type ImplTrait; + + fn f() -> Self::ImplTrait; +} + +struct S<T>(T); + +trait Associated { + type A; +} + +impl<'a, T: Associated<A = &'a ()>> AssociatedImpl for S<T> { + type ImplTrait = impl core::fmt::Debug; + + fn f() -> Self::ImplTrait { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs new file mode 100644 index 000000000..2ba4befea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs @@ -0,0 +1,25 @@ +// Regression test for issues #84660 and #86411: both are variations on #76202. +// Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header. + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +type Bar = impl Foo; +fn _defining_use() -> Bar {} + +trait TraitArg<T> { + fn f(); +} + +impl TraitArg<Bar> for () { + fn f() { + println!("ho"); + } +} + +fn main() { + <() as TraitArg<Bar>>::f(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs new file mode 100644 index 000000000..48d4b0c96 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -0,0 +1,41 @@ +// Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an +// impl header being accepted was used to create unsoundness. + +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +type Bar = impl Foo; +fn _defining_use() -> Bar {} + +trait Trait<T, In> { + type Out; + fn convert(i: In) -> Self::Out; +} + +impl<In, Out> Trait<Bar, In> for Out { + type Out = Out; + fn convert(_i: In) -> Self::Out { + unreachable!(); + } +} + +impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>` + type Out = In; + fn convert(i: In) -> Self::Out { + i + } +} + +fn transmute<In, Out>(i: In) -> Out { + <Out as Trait<Bar, In>>::convert(i) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = transmute::<&String, &String>(&x); + } + println!("{}", d); +} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr new file mode 100644 index 000000000..6a75e1bd2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait<Bar, _>` + --> $DIR/issue-84660-unsoundness.rs:23:1 + | +LL | impl<In, Out> Trait<Bar, In> for Out { + | ------------------------------------ first implementation here +... +LL | impl<In, Out> Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs new file mode 100644 index 000000000..80a74eb63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs @@ -0,0 +1,73 @@ +// check-pass + +use std::error::Error as StdError; +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Stream { + type Item; + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>; + fn size_hint(&self) -> (usize, Option<usize>) { + (0, None) + } +} + +pub trait TryStream: Stream { + type Ok; + type Error; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Ok, Self::Error>>>; +} + +impl<S, T, E> TryStream for S +where + S: ?Sized + Stream<Item = Result<T, E>>, +{ + type Ok = T; + type Error = E; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Ok, Self::Error>>> { + self.poll_next(cx) + } +} + +pub trait ServerSentEvent: Sized + Send + Sync + 'static {} + +impl<T: Send + Sync + 'static> ServerSentEvent for T {} + +struct SseKeepAlive<S> { + event_stream: S, +} + +struct SseComment<T>(T); + +impl<S> Stream for SseKeepAlive<S> +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent, + S::Error: StdError + Send + Sync + 'static, +{ + type Item = Result<SseComment<&'static str>, ()>; + fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> { + unimplemented!() + } +} + +pub fn keep<S>( + event_stream: S, +) -> impl TryStream<Ok = impl ServerSentEvent + Send + 'static, Error = ()> + Send + 'static +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent + Send, + S::Error: StdError + Send + Sync + 'static, +{ + SseKeepAlive { event_stream } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-89686.rs b/tests/ui/type-alias-impl-trait/issue-89686.rs new file mode 100644 index 000000000..058417bdb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89686.rs @@ -0,0 +1,23 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +type G<'a, T> = impl Future<Output = ()> + 'a; + +trait Trait { + type F: Future<Output = ()>; + + fn f(&self) -> Self::F; + + fn g<'a>(&'a self) -> G<'a, Self> + where + Self: Sized, + { + async move { self.f().await } + //~^ ERROR: the trait bound `T: Trait` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr new file mode 100644 index 000000000..3b95a575a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/issue-89686.rs:18:9 + | +LL | async move { self.f().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type G<'a, T: Trait> = impl Future<Output = ()> + 'a; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-89952.rs b/tests/ui/type-alias-impl-trait/issue-89952.rs new file mode 100644 index 000000000..dc0f19c04 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89952.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} +impl SomeTrait for () {} + +trait MyFuture { + type Output; +} +impl<T> MyFuture for T { + type Output = T; +} + +trait ReturnsFuture { + type Output: SomeTrait; + type Future: MyFuture<Output = Result<Self::Output, ()>>; + fn func() -> Self::Future; +} + +struct Foo; + +impl ReturnsFuture for Foo { + type Output = impl SomeTrait; + type Future = impl MyFuture<Output = Result<Self::Output, ()>>; + fn func() -> Self::Future { + Result::<(), ()>::Err(()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.rs b/tests/ui/type-alias-impl-trait/issue-90400-1.rs new file mode 100644 index 000000000..15aead2f6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.rs @@ -0,0 +1,29 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +trait Foo { + type FooFn<B>: FnOnce(); + + fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B>; +} + +struct MyFoo; + +impl Foo for MyFoo { + type FooFn<B> = impl FnOnce(); + + fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> { + move || bar.bar() //~ ERROR: the trait bound `B: Bar` is not satisfied + } +} + +fn main() { + let boom: <MyFoo as Foo>::FooFn<u32> = unsafe { core::mem::zeroed() }; + boom(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr new file mode 100644 index 000000000..ead28769f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/issue-90400-1.rs:22:9 + | +LL | move || bar.bar() + | ^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `<MyFoo as Foo>::foo` + --> $DIR/issue-90400-1.rs:21:15 + | +LL | fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> { + | ^^^ required by this bound in `<MyFoo as Foo>::foo` +help: consider restricting type parameter `B` + | +LL | type FooFn<B: Bar> = impl FnOnce(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.rs b/tests/ui/type-alias-impl-trait/issue-90400-2.rs new file mode 100644 index 000000000..4c6e893c1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.rs @@ -0,0 +1,37 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +trait Baz { + fn baz(&self); +} + +trait Foo { + type FooFn<B>: Baz; + + fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B>; +} + +struct MyFoo; +impl Foo for MyFoo { + type FooFn<B> = impl Baz; + + fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> { + MyBaz(bar) //~ ERROR: the trait bound `B: Bar` is not satisfied + } +} + +struct MyBaz<B: Bar>(B); +impl<B: Bar> Baz for MyBaz<B> { + fn baz(&self) {} +} + +fn main() { + let boom: <MyFoo as Foo>::FooFn<u32> = unsafe { core::mem::zeroed() }; + boom.baz(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr new file mode 100644 index 000000000..0c45046f5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/issue-90400-2.rs:25:9 + | +LL | MyBaz(bar) + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required for `MyBaz<B>` to implement `Baz` + --> $DIR/issue-90400-2.rs:30:14 + | +LL | impl<B: Bar> Baz for MyBaz<B> { + | --- ^^^ ^^^^^^^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `B` + | +LL | type FooFn<B: Bar> = impl Baz; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs new file mode 100644 index 000000000..1f8c78926 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-93411.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +// this test used to stack overflow due to infinite recursion. +// check-pass +// compile-flags: --edition=2018 + +use std::future::Future; + +fn main() { + let _ = move || async move { + let value = 0u8; + blah(&value).await; + }; +} + +type BlahFut<'a> = impl Future<Output = ()> + Send + 'a; +fn blah<'a>(_value: &'a u8) -> BlahFut<'a> { + async {} +} diff --git a/tests/ui/type-alias-impl-trait/issue-94429.rs b/tests/ui/type-alias-impl-trait/issue-94429.rs new file mode 100644 index 000000000..2c965b875 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-94429.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait, generator_trait, generators)] +use std::ops::Generator; + +trait Runnable { + type Gen: Generator<Yield = (), Return = ()>; + + fn run(&mut self) -> Self::Gen; +} + +struct Implementor {} + +impl Runnable for Implementor { + type Gen = impl Generator<Yield = (), Return = ()>; + + fn run(&mut self) -> Self::Gen { + //~^ ERROR: type mismatch resolving + move || { + yield 1; + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr new file mode 100644 index 000000000..8d7f7a07b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<[generator@$DIR/issue-94429.rs:17:9: 17:16] as Generator>::Yield == ()` + --> $DIR/issue-94429.rs:15:26 + | +LL | fn run(&mut self) -> Self::Gen { + | ^^^^^^^^^ expected integer, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs new file mode 100644 index 000000000..825710851 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + match foo { + None => (), + Some((a, b, c)) => (), //~ ERROR mismatched types + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr new file mode 100644 index 000000000..728244a18 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-96572-unconstrained-mismatch.rs:8:14 + | +LL | match foo { + | --- this expression has type `T` +LL | None => (), +LL | Some((a, b, c)) => (), + | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `(u32, u32)` + found tuple `(_, _, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs new file mode 100644 index 000000000..2c740ccc1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -0,0 +1,92 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +fn main() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + match foo { + None => (), + Some((a, b)) => (), + } +} + +fn upvar() { + #[derive(Copy, Clone)] + struct Foo((u32, u32)); + + type T = impl Copy; + let foo: T = Foo((1u32, 2u32)); + let x = move || { + let Foo((a, b)) = foo; + }; +} + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some((a, b)) => (), + } + }; +} + +fn r#struct() { + #[derive(Copy, Clone)] + struct Foo((u32, u32)); + + type U = impl Copy; + let foo: U = Foo((1u32, 2u32)); + let Foo((a, b)) = foo; +} + +mod only_pattern { + type T = impl Copy; + + fn foo(foo: T) { + let (mut x, mut y) = foo; + x = 42; + y = "foo"; + } + + type U = impl Copy; + + fn bar(bar: Option<U>) { + match bar { + Some((mut x, mut y)) => { + x = 42; + y = "foo"; + } + None => {} + } + } +} + +mod only_pattern_rpit { + #[allow(unconditional_recursion)] + fn foo(b: bool) -> impl Copy { + let (mut x, mut y) = foo(false); + x = 42; + y = "foo"; + if b { + panic!() + } else { + foo(true) + } + } + + fn bar(b: bool) -> Option<impl Copy> { + if b { + return None; + } + match bar(!b) { + Some((mut x, mut y)) => { + x = 42; + y = "foo"; + } + None => {} + } + None + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-98604.rs b/tests/ui/type-alias-impl-trait/issue-98604.rs new file mode 100644 index 000000000..32c2f9ed5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98604.rs @@ -0,0 +1,11 @@ +// edition:2018 + +type AsyncFnPtr = Box<dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>>; + +async fn test() {} + +#[allow(unused_must_use)] +fn main() { + Box::new(test) as AsyncFnPtr; + //~^ ERROR expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>` +} diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr new file mode 100644 index 000000000..92d01eb0d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr @@ -0,0 +1,18 @@ +error[E0271]: expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>` + --> $DIR/issue-98604.rs:9:5 + | +LL | Box::new(test) as AsyncFnPtr; + | ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98604.rs:5:17 + | +LL | async fn test() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>` + found opaque type `impl Future<Output = ()>` + = note: required for the cast from `fn() -> impl Future<Output = ()> {test}` to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-98608.rs b/tests/ui/type-alias-impl-trait/issue-98608.rs new file mode 100644 index 000000000..1f89af045 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98608.rs @@ -0,0 +1,11 @@ +fn hi() -> impl Sized { + std::ptr::null::<u8>() +} + +fn main() { + let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi); + //~^ ERROR expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized` + let boxed = b(); + let null = *boxed; + println!("{null:?}"); +} diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr new file mode 100644 index 000000000..916a58451 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr @@ -0,0 +1,16 @@ +error[E0271]: expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized` + --> $DIR/issue-98608.rs:6:39 + | +LL | fn hi() -> impl Sized { + | ---------- the found opaque type +... +LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi); + | ^^^^^^^^^^^^ expected struct `Box`, found opaque type + | + = note: expected struct `Box<u8>` + found opaque type `impl Sized` + = note: required for the cast from `fn() -> impl Sized {hi}` to the object type `dyn Fn() -> Box<u8>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs new file mode 100644 index 000000000..01d1f5db1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs @@ -0,0 +1,7 @@ +#![feature(type_alias_impl_trait)] + +type Opaque<'a, T> = impl Sized; +fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } +//~^ ERROR: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr new file mode 100644 index 000000000..65a0af0d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds + --> $DIR/missing_lifetime_bound.rs:4:47 + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } + | -- ^ + | | + | hidden type `&'a i32` captures the lifetime `'a` as defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs new file mode 100644 index 000000000..b887fcf30 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type Y<A, B> = impl std::fmt::Debug; + +fn g<A, B>() -> (Y<A, B>, Y<B, A>) { + (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr new file mode 100644 index 000000000..278117009 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 + | +LL | (42_i64, 60) + | ^^^^^^^^^^^^ + | | + | expected `i64`, got `i32` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs new file mode 100644 index 000000000..65eb2952e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, i) //~ ERROR concrete type differs from previous +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr new file mode 100644 index 000000000..d7676b8e9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 + | +LL | (i, i) + | ^^^^^^ + | | + | expected `&'a i32`, got `&'b i32` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs new file mode 100644 index 000000000..21fca047a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +type X<A: ToString + Clone, B: ToString + Clone> = impl ToString; + +fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) { + (a.clone(), a) +} + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, j) +} + +fn main() { + println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1)); + let meh = 42; + let muh = 69; + println!("{:?}", foo(&meh, &muh)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs new file mode 100644 index 000000000..da845e861 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X<A, B> = impl Into<&'static A>; + +fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) { + //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied + (a, a) +} + +fn main() { + println!("{}", <X<_, _> as Into<&String>>::into(f(&[1isize, 2, 3], String::new()).1)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr new file mode 100644 index 000000000..66a6b0bbf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied + --> $DIR/multiple-def-uses-in-one-fn.rs:9:45 + | +LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) { + | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | + = note: required for `&A` to implement `Into<&'static B>` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> { + | ++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs new file mode 100644 index 000000000..14510a529 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X<A: ToString + Clone, B: ToString + Clone> = impl ToString; + +fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) { + (a.clone(), a) + //~^ ERROR concrete type differs from previous defining opaque type +} + +fn main() { + println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr new file mode 100644 index 000000000..0f752212a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 + | +LL | (a.clone(), a) + | ^^^^^^^^^^^^^^ + | | + | expected `A`, got `B` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs new file mode 100644 index 000000000..11a922443 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X<A: ToString + Clone, B: ToString + Clone> = impl ToString; + +fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) { + (a, b) +} + +fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) { + (a, b) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr new file mode 100644 index 000000000..bbe709dcc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 + | +LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) { + | - - found type parameter + | | + | expected type parameter +LL | (a, b) + | ^ expected type parameter `A`, found type parameter `B` + | + = note: expected type parameter `A` + found type parameter `B` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/multiple_definitions.rs b/tests/ui/type-alias-impl-trait/multiple_definitions.rs new file mode 100644 index 000000000..9e6268e63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple_definitions.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct ConcreteError {} +pub trait IoBase {} +struct X {} +impl IoBase for X {} + +pub struct ClusterIterator<B, E, S = B> { + pub fat: B, + phantom_s: PhantomData<S>, + phantom_e: PhantomData<E>, +} + +pub struct FileSystem<IO: IoBase> { + pub disk: IO, +} + +impl<IO: IoBase> FileSystem<IO> { + pub fn cluster_iter(&self) -> ClusterIterator<impl IoBase + '_, ConcreteError> { + ClusterIterator { + fat: X {}, + phantom_s: PhantomData::default(), + phantom_e: PhantomData::default(), + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs new file mode 100644 index 000000000..822489716 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; + +trait Foo<A> { } + +impl Foo<()> for () { } + +fn foo() -> impl Foo<FooX> { + //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied + // FIXME(type-alias-impl-trait): We could probably make this work. + () +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr new file mode 100644 index 000000000..62db019ed --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied + --> $DIR/nested-tait-inference.rs:12:13 + | +LL | fn foo() -> impl Foo<FooX> { + | ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()` +... +LL | () + | -- return type was inferred to be `()` here + | + = help: the trait `Foo<()>` is implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs new file mode 100644 index 000000000..0d7f5bad2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; + +trait Foo<A> {} + +impl Foo<()> for () {} +impl Foo<u32> for () {} + +fn foo() -> impl Foo<FooX> { + //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied + () +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr new file mode 100644 index 000000000..f4d96038d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied + --> $DIR/nested-tait-inference2.rs:13:13 + | +LL | fn foo() -> impl Foo<FooX> { + | ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()` +LL | +LL | () + | -- return type was inferred to be `()` here + | + = help: the following other types implement trait `Foo<A>`: + <() as Foo<()>> + <() as Foo<u32>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs new file mode 100644 index 000000000..b0ebdd1bf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; +//~^ ERROR unconstrained opaque type + +trait Foo<A> { } + +impl Foo<FooX> for () { } + +fn foo() -> impl Foo<FooX> { + () +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr new file mode 100644 index 000000000..b1d947a9c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/nested-tait-inference3.rs:6:13 + | +LL | type FooX = impl Debug; + | ^^^^^^^^^^ + | + = note: `FooX` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/nested.rs b/tests/ui/type-alias-impl-trait/nested.rs new file mode 100644 index 000000000..6b866be7d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl Trait<Foo>; + +trait Trait<T> {} + +impl<T, U> Trait<T> for U {} + +fn bar() -> Bar { + 42 +} + +fn main() { + println!("{:?}", bar()); + //~^ ERROR `Bar` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr new file mode 100644 index 000000000..732af5c0b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested.stderr @@ -0,0 +1,12 @@ +error[E0277]: `Bar` doesn't implement `Debug` + --> $DIR/nested.rs:15:22 + | +LL | println!("{:?}", bar()); + | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `Bar` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs new file mode 100644 index 000000000..60b6e1aac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +mod my_mod { + use std::fmt::Debug; + + pub type Foo = impl Debug; + pub type Foot = impl Debug; + + pub fn get_foo() -> Foo { + 5i32 + } + + pub fn get_foot() -> Foot { + get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type + } +} + +fn main() { + let _: my_mod::Foot = my_mod::get_foot(); +} diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr new file mode 100644 index 000000000..fa6ecf68d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/nested_type_alias_impl_trait.rs:14:9 + | +LL | get_foo() + | ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/nested_type_alias_impl_trait.rs:7:21 + | +LL | pub type Foot = impl Debug; + | ^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/nested_type_alias_impl_trait.rs:6:20 + | +LL | pub type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs new file mode 100644 index 000000000..fed5ac07c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +// check-pass +fn main() {} + +type NoReveal = impl std::fmt::Debug; + +fn define_no_reveal() -> NoReveal { + "" +} + +fn no_reveal(x: NoReveal) { + let _: &'static str = x; + let _ = x as &'static str; +} diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs new file mode 100644 index 000000000..0f0a02e97 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -0,0 +1,18 @@ +// Issue 52985: user code provides no use case that allows a type alias `impl Trait` +// We now emit a 'unconstrained opaque type' error + +#![feature(type_alias_impl_trait)] + +mod foo { + pub type Foo = impl Copy; + //~^ ERROR unconstrained opaque type + + // make compiler happy about using 'Foo' + pub fn bar(x: Foo) -> Foo { + x + } +} + +fn main() { + let _: foo::Foo = std::mem::transmute(0u8); +} diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr new file mode 100644 index 000000000..f3e8ae9c7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/no_inferrable_concrete_type.rs:7:20 + | +LL | pub type Foo = impl Copy; + | ^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs new file mode 100644 index 000000000..61153b1e1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +mod boo { + pub type Boo = impl ::std::fmt::Debug; + fn bomp() -> Boo { + "" + } +} + +// We don't actually know the type here. + +fn bomp2() { + let _: &str = bomp(); //~ ERROR mismatched types +} + +fn bomp() -> boo::Boo { + "" //~ ERROR mismatched types +} + +fn bomp_loop() -> boo::Boo { + loop {} +} diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr new file mode 100644 index 000000000..ae03a5b3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/no_revealing_outside_defining_module.rs:15:19 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the found opaque type +... +LL | let _: &str = bomp(); + | ---- ^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `Boo` + +error[E0308]: mismatched types + --> $DIR/no_revealing_outside_defining_module.rs:19:5 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the expected opaque type +... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type +LL | "" + | ^^ expected opaque type, found `&str` + | + = note: expected opaque type `Boo` + found reference `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs new file mode 100644 index 000000000..fa47d13f5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -0,0 +1,36 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two<T, U> = impl Debug; + +fn three<T: Debug, U>(t: T) -> Two<T, U> { + (t, 5i8) + //~^ ERROR `T` doesn't implement `Debug` +} + +trait Bar { + type Blub: Debug; + const FOO: Self::Blub; +} + +impl Bar for u32 { + type Blub = i32; + const FOO: i32 = 42; +} + +fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { + (t, <U as Bar>::FOO) + //~^ ERROR `U: Bar` is not satisfied + //~| ERROR `T` doesn't implement `Debug` +} + +fn is_sync<T: Sync>() {} + +fn asdfl() { + //FIXME(oli-obk): these currently cause cycle errors + //is_sync::<Two<i32, u32>>(); + //is_sync::<Two<i32, *const i32>>(); +} diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr new file mode 100644 index 000000000..b11198c58 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -0,0 +1,38 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/not_a_defining_use.rs:10:5 + | +LL | (t, 5i8) + | ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, i8)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error[E0277]: the trait bound `U: Bar` is not satisfied + --> $DIR/not_a_defining_use.rs:25:5 + | +LL | (t, <U as Bar>::FOO) + | ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U` + | +help: consider restricting type parameter `U` + | +LL | type Two<T, U: Bar> = impl Debug; + | +++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/not_a_defining_use.rs:25:5 + | +LL | (t, <U as Bar>::FOO) + | ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, _)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.rs b/tests/ui/type-alias-impl-trait/not_well_formed.rs new file mode 100644 index 000000000..fbb7a4d58 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_well_formed.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait TraitWithAssoc { + type Assoc; +} + +type Foo<V> = impl Trait<V::Assoc>; //~ associated type `Assoc` not found for `V` + +trait Trait<U> {} + +impl<W> Trait<W> for () {} + +fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T> { + () +} diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr new file mode 100644 index 000000000..c36b95f47 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/not_well_formed.rs:9:29 + | +LL | type Foo<V> = impl Trait<V::Assoc>; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs new file mode 100644 index 000000000..b8fac45b7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs @@ -0,0 +1,18 @@ +// Here we process outlive obligations involving +// opaque types with bound vars in substs. +// This was an ICE. +// +// check-pass +#![feature(type_alias_impl_trait)] + +type Ty<'a> = impl Sized + 'a; +fn define<'a>() -> Ty<'a> {} + +// Ty<'^0>: 'static +fn test1(_: &'static fn(Ty<'_>)) {} + +fn test2() { + None::<&fn(Ty<'_>)>; +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs new file mode 100644 index 000000000..7ecb55353 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR cycle detected + +fn is_send<T: Send>() { } + +fn not_good() { + // Error: this function does not constrain `Foo` to any particular + // hidden type, so it cannot rely on `Send` being true. + is_send::<Foo>(); +} + +fn not_gooder() { + // Constrain `Foo = u32` + let x: Foo = 22_u32; + + // while we could know this from the hidden type, it would + // need extra roundabout logic to support it. + is_send::<Foo>(); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr new file mode 100644 index 000000000..27fded333 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -0,0 +1,28 @@ +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_good`... + --> $DIR/reveal_local.rs:13:5 + | +LL | is_send::<Foo>(); + | ^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs new file mode 100644 index 000000000..8781196c3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl PartialEq<Foo>; + +fn bar() -> Bar { + 42_i32 //~^ ERROR can't compare `i32` with `Foo` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.stderr new file mode 100644 index 000000000..c2cf70687 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: can't compare `i32` with `Foo` + --> $DIR/self-referential-2.rs:6:13 + | +LL | fn bar() -> Bar { + | ^^^ no implementation for `i32 == Foo` +LL | 42_i32 + | ------ return type was inferred to be `i32` here + | + = help: the trait `PartialEq<Foo>` is not implemented for `i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs new file mode 100644 index 000000000..d40715717 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i +} + +fn main() { + let meh = 42; + let muh = 42; + assert_eq!(bar(&meh), bar(&muh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.rs b/tests/ui/type-alias-impl-trait/self-referential-4.rs new file mode 100644 index 000000000..36742c8ad --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-4.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'static>> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Bar<'b, 'static>` +} + +type Foo<'a, 'b> = impl PartialEq<Foo<'static, 'b>> + std::fmt::Debug; + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Foo<'static, 'b>` +} + +type Moo<'a, 'b> = impl PartialEq<Moo<'static, 'a>> + std::fmt::Debug; + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Moo<'static, 'a>` +} + +fn main() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.stderr b/tests/ui/type-alias-impl-trait/self-referential-4.stderr new file mode 100644 index 000000000..98c762e3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-4.stderr @@ -0,0 +1,36 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'static>` + --> $DIR/self-referential-4.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'static>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` + --> $DIR/self-referential-4.rs:11:31 + | +LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Foo<'static, 'b>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` + --> $DIR/self-referential-4.rs:17:31 + | +LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Moo<'static, 'a>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs new file mode 100644 index 000000000..3ff5406a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'a>> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + //~^ ERROR can't compare `&i32` with `Bar<'b, 'a>` + i +} + +type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug); + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + //~^ ERROR can't compare `&i32` with `(i32, &i32)` + (42, i) +} + +type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug); + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + (42, i) +} + +fn main() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr new file mode 100644 index 000000000..aff489d70 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -0,0 +1,39 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'a>` + --> $DIR/self-referential.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'a>` +LL | +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `(i32, &i32)` + --> $DIR/self-referential.rs:12:31 + | +LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, &i32)` +LL | +LL | (42, i) + | ------- return type was inferred to be `(i32, &i32)` here + | + = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + --> $DIR/self-referential.rs:19:31 + | +LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` +LL | +LL | (42, i) + | ------- return type was inferred to be `(i32, &i32)` here + | + = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self_implication.rs b/tests/ui/type-alias-impl-trait/self_implication.rs new file mode 100644 index 000000000..4e805ee30 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self_implication.rs @@ -0,0 +1,38 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +fn foo() { + struct Foo<'a> { + x: &'a mut u8, + } + impl<'a> Foo<'a> { + fn foo(&self) -> impl Sized {} + } + // use site + let mut x = 5; + let y = Foo { x: &mut x }; + let z = y.foo(); + let _a = &x; // invalidate the `&'a mut`in `y` + let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live +} + +fn bar() { + struct Foo<'a> { + x: &'a mut u8, + } + + // desugared + type FooX<'a> = impl Sized; + impl<'a> Foo<'a> { + fn foo(&self) -> FooX<'a> {} + } + + // use site + let mut x = 5; + let y = Foo { x: &mut x }; + let z = y.foo(); + let _a = &x; // invalidate the `&'a mut`in `y` + let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/static-const-types.rs b/tests/ui/type-alias-impl-trait/static-const-types.rs new file mode 100644 index 000000000..748a279e4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/static-const-types.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// check-pass + +use std::fmt::Debug; + +type Foo = impl Debug; + +static FOO1: Foo = 22_u32; +const FOO2: Foo = 22_u32; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs new file mode 100644 index 000000000..c2ab6a9d1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +type Bar = impl Send; + +// While i32 is structural-match, we do not want to leak this information. +// (See https://github.com/rust-lang/rust/issues/72156) +const fn leak_free() -> Bar { + 7i32 +} +const LEAK_FREE: Bar = leak_free(); + +fn leak_free_test() { + match LEAK_FREE { + LEAK_FREE => (), + //~^ `Bar` cannot be used in patterns + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr new file mode 100644 index 000000000..dbc183f54 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -0,0 +1,8 @@ +error: `Bar` cannot be used in patterns + --> $DIR/structural-match-no-leak.rs:14:9 + | +LL | LEAK_FREE => (), + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/structural-match.rs b/tests/ui/type-alias-impl-trait/structural-match.rs new file mode 100644 index 000000000..7cc9ccaab --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Send; + +// This is not structural-match +struct A; + +const fn value() -> Foo { + A +} +const VALUE: Foo = value(); + +fn test() { + match VALUE { + VALUE => (), + //~^ `Foo` cannot be used in patterns + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr new file mode 100644 index 000000000..61287f268 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match.stderr @@ -0,0 +1,8 @@ +error: `Foo` cannot be used in patterns + --> $DIR/structural-match.rs:15:9 + | +LL | VALUE => (), + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs new file mode 100644 index 000000000..f6a830296 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = Box<dyn Iterator<Item = impl Send>>; + +fn make_foo() -> Foo { + Box::new(vec![1, 2, 3].into_iter()) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs new file mode 100644 index 000000000..fddecfcac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = impl Iterator<Item = impl Send>; + +fn make_foo() -> Foo { + vec![1, 2].into_iter() +} + +type Bar = impl Send; +type Baz = impl Iterator<Item = Bar>; + +fn make_baz() -> Baz { + vec!["1", "2"].into_iter() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs new file mode 100644 index 000000000..5630e036b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] +// check-pass +// Ensures that `const` items can constrain an opaque `impl Trait`. + +use std::fmt::Debug; + +pub type Foo = impl Debug; + +const _FOO: Foo = 5; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs new file mode 100644 index 000000000..857066c78 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME: this is ruled out for now but should work + +type Foo = fn() -> impl Send; +//~^ ERROR: `impl Trait` only allowed in function and inherent method return types + +fn make_foo() -> Foo { + || 15 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr new file mode 100644 index 000000000..a31cf1a51 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/type-alias-impl-trait-fn-type.rs:6:20 + | +LL | type Foo = fn() -> impl Send; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs new file mode 100644 index 000000000..07c891f06 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +// Regression test for issue #61863 + +pub trait MyTrait {} + +#[derive(Debug)] +pub struct MyStruct { + v: u64, +} + +impl MyTrait for MyStruct {} + +pub fn bla() -> TE { + return MyStruct { v: 1 }; +} + +pub fn bla2() -> TE { + bla() +} + +type TE = impl MyTrait; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs new file mode 100644 index 000000000..c5e8068e5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type A = impl Sized; +fn f1() -> A { + 0 +} + +type B = impl ?Sized; +fn f2() -> &'static B { + &[0] +} + +type C = impl ?Sized + 'static; +fn f3() -> &'static C { + &[0] +} + +type D = impl ?Sized; +fn f4() -> &'static D { + &1 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs new file mode 100644 index 000000000..1a4064055 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = Vec<impl Send>; + +fn make_foo() -> Foo { + vec![true, false] +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs new file mode 100644 index 000000000..1f2d0e47e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +pub trait MyTrait {} + +impl MyTrait for bool {} + +type Foo = impl MyTrait; + +struct Blah { + my_foo: Foo, + my_u8: u8, +} + +impl Blah { + fn new() -> Blah { + Blah { my_foo: make_foo(), my_u8: 12 } + } + fn into_inner(self) -> (Foo, u8, Foo) { + (self.my_foo, self.my_u8, make_foo()) + } +} + +fn make_foo() -> Foo { + true +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs new file mode 100644 index 000000000..efbf4f1e3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs @@ -0,0 +1,18 @@ +// regression test for #74018 + +#![feature(type_alias_impl_trait)] + +trait Trait { + type Associated; + fn into(self) -> Self::Associated; +} + +impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) { + //~^ ERROR the lifetime parameter `'a` is not constrained + type Associated = (i32, impl Iterator<Item = i32>); + fn into(self) -> Self::Associated { + (0_i32, [0_i32].iter().copied()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr new file mode 100644 index 000000000..8cdce2f8e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:10:6 + | +LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs new file mode 100644 index 000000000..e5e7fb677 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> Foo; +//~^ ERROR: unconstrained opaque type + +fn crash(x: Foo) -> Foo { + x +} + +fn main() { + +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr new file mode 100644 index 000000000..a770eeac3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12 + | +LL | type Foo = impl Fn() -> Foo; + | ^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs new file mode 100644 index 000000000..7c7a1b405 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +pub trait Bar<T> { + type Item; +} + +type Foo = impl Bar<Foo, Item = Foo>; +//~^ ERROR: unconstrained opaque type + +fn crash(x: Foo) -> Foo { + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr new file mode 100644 index 000000000..3f3699ce5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12 + | +LL | type Foo = impl Bar<Foo, Item = Foo>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs new file mode 100644 index 000000000..8ca279eec --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn foo() -> Foo { + "foo" +} + +fn bar() -> impl 'static { //~ ERROR: at least one trait must be specified + "foo" +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr new file mode 100644 index 000000000..3f7acd338 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr @@ -0,0 +1,14 @@ +error: at least one trait must be specified + --> $DIR/type-alias-impl-trait-with-no-traits.rs:3:12 + | +LL | type Foo = impl 'static; + | ^^^^^^^^^^^^ + +error: at least one trait must be specified + --> $DIR/type-alias-impl-trait-with-no-traits.rs:10:13 + | +LL | fn bar() -> impl 'static { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs new file mode 100644 index 000000000..70c2ee427 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -0,0 +1,79 @@ +// check-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(type_alias_impl_trait)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]); +} + +// single definition +type Foo = impl std::fmt::Display; + +fn foo() -> Foo { + "foo" +} + +// two definitions +type Bar = impl std::fmt::Display; + +fn bar1() -> Bar { + "bar1" +} + +fn bar2() -> Bar { + "bar2" +} + +type MyIter<T> = impl Iterator<Item = T>; + +fn my_iter<T>(t: T) -> MyIter<T> { + std::iter::once(t) +} + +fn my_iter2<T>(t: T) -> MyIter<T> { + std::iter::once(t) +} + +// param names should not have an effect! +fn my_iter3<U>(u: U) -> MyIter<U> { + std::iter::once(u) +} + +// param position should not have an effect! +fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> { + std::iter::once(v) +} + +// param names should not have an effect! +type MyOtherIter<T> = impl Iterator<Item = T>; + +fn my_other_iter<U>(u: U) -> MyOtherIter<U> { + std::iter::once(u) +} + +trait Trait {} +type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; + +fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t +} + +mod pass_through { + pub type Passthrough<T: 'static> = impl Sized + 'static; + + fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> { + t + } +} + +fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> { + x +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs new file mode 100644 index 000000000..67f56bcde --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs @@ -0,0 +1,84 @@ +// check-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(type_alias_impl_trait)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]); +} + +use defining_use_scope::*; + +mod defining_use_scope { + // single definition + pub type Foo = impl std::fmt::Display; + + pub fn foo() -> Foo { + "foo" + } + + // two definitions + pub type Bar = impl std::fmt::Display; + + pub fn bar1() -> Bar { + "bar1" + } + + pub fn bar2() -> Bar { + "bar2" + } + + pub type MyIter<T> = impl Iterator<Item = T>; + + pub fn my_iter<T>(t: T) -> MyIter<T> { + std::iter::once(t) + } + + fn my_iter2<T>(t: T) -> MyIter<T> { + std::iter::once(t) + } + + // param names should not have an effect! + fn my_iter3<U>(u: U) -> MyIter<U> { + std::iter::once(u) + } + + // param position should not have an effect! + fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> { + std::iter::once(v) + } + + // param names should not have an effect! + type MyOtherIter<T> = impl Iterator<Item = T>; + + fn my_other_iter<U>(u: U) -> MyOtherIter<U> { + std::iter::once(u) + } + + trait Trait {} + type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; + + fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t + } + + mod pass_through { + pub type Passthrough<T: 'static> = impl Sized + 'static; + + fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> { + t + } + } + + fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> { + x + } + +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs new file mode 100644 index 000000000..fd954801d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +use std::iter::{once, Chain}; + +type I<A> = Chain<A, impl Iterator<Item = &'static str>>; +fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> { + x.chain(once("5")) +} + +fn main() { + assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::<Vec<_>>()); +} diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs new file mode 100644 index 000000000..4e9d1788b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type Foo = impl Debug; + +fn foo1() -> u32 { + let x: Foo = 22_u32; + x +} + +fn foo2() -> u32 { + let x: Foo = 22_u32; + let y: Foo = x; + same_type((x, y)); //~ ERROR use of moved value + y //~ ERROR use of moved value +} + +fn same_type<T>(x: (T, T)) {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr new file mode 100644 index 000000000..1dabe4586 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `x` + --> $DIR/type_of_a_let.rs:16:16 + | +LL | let x: Foo = 22_u32; + | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait +LL | let y: Foo = x; + | - value moved here +LL | same_type((x, y)); + | ^ value used here after move + +error[E0382]: use of moved value: `y` + --> $DIR/type_of_a_let.rs:17:5 + | +LL | let y: Foo = x; + | - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait +LL | same_type((x, y)); + | - value moved here +LL | y + | ^ value used here after move + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs new file mode 100644 index 000000000..f43ad7dce --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type Opaque<T> = impl Sized; +fn defining<T>() -> Opaque<T> {} +struct Ss<'a, T>(&'a Opaque<T>); + + +fn test<'a, T>(_: Ss<'a, T>) { + // test that we have an implied bound `Opaque<T>: 'a` from fn signature + None::<&'a Opaque<T>>; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.rs b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs new file mode 100644 index 000000000..aa537dfc9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait Trait { + fn foo<T, U>(t: T) -> U; +} + +trait ProofForConversion<X> { + fn convert<T, U>(_: PhantomData<Self>, r: T) -> U; +} + +impl<X: Trait> ProofForConversion<X> for () { + fn convert<T, U>(_: PhantomData<Self>, r: T) -> U { + X::foo(r) + } +} + +type Converter<T> = impl ProofForConversion<T>; + +fn _defining_use<T: Trait>() -> Converter<T> { + () + //~^ ERROR the trait bound `T: Trait` is not satisfied +} + + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr new file mode 100644 index 000000000..103636b6c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/underconstrained_generic.rs:22:5 + | +LL | () + | ^^ the trait `Trait` is not implemented for `T` + | +note: required for `()` to implement `ProofForConversion<T>` + --> $DIR/underconstrained_generic.rs:13:16 + | +LL | impl<X: Trait> ProofForConversion<X> for () { + | ----- ^^^^^^^^^^^^^^^^^^^^^ ^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `T` + | +LL | type Converter<T: Trait> = impl ProofForConversion<T>; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs new file mode 100644 index 000000000..c5b2e8a1c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs @@ -0,0 +1,34 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait ProofForConversion<'a, 'b> { + fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T; +} + +impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () { + fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T { + r + } +} + +type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; +//~^ ERROR reference has a longer lifetime than the data it references + +// Even _defining_use with an explicit `'a: 'b` compiles fine, too. +fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { + x +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + Converter::<'a, 'b>::convert(PhantomData, x) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = extend_lifetime(&x); + } + println!("{}", d); +} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr new file mode 100644 index 000000000..12d85a49d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/underconstrained_lifetime.rs:15:26 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined here + --> $DIR/underconstrained_lifetime.rs:15:20 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/underconstrained_lifetime.rs:15:16 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.rs b/tests/ui/type-alias-impl-trait/unnameable_type.rs new file mode 100644 index 000000000..1739ab006 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unnameable_type.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// This test ensures that unnameable types stay unnameable +// https://github.com/rust-lang/rust/issues/63063#issuecomment-1360053614 + +// library +mod private { + pub struct Private; + pub trait Trait { + fn dont_define_this(_private: Private) {} + } +} + +use private::Trait; + +// downstream +type MyPrivate = impl Sized; +//~^ ERROR: unconstrained opaque type +impl Trait for u32 { + fn dont_define_this(_private: MyPrivate) {} + //~^ ERROR: incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr new file mode 100644 index 000000000..7dc6efc4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -0,0 +1,31 @@ +error: unconstrained opaque type + --> $DIR/unnameable_type.rs:17:18 + | +LL | type MyPrivate = impl Sized; + | ^^^^^^^^^^ + | + = note: `MyPrivate` must be used in combination with a concrete type within the same module + +error[E0053]: method `dont_define_this` has an incompatible type for trait + --> $DIR/unnameable_type.rs:20:35 + | +LL | type MyPrivate = impl Sized; + | ---------- the found opaque type +... +LL | fn dont_define_this(_private: MyPrivate) {} + | ^^^^^^^^^ + | | + | expected struct `Private`, found opaque type + | help: change the parameter type to match the trait: `Private` + | +note: type in trait + --> $DIR/unnameable_type.rs:10:39 + | +LL | fn dont_define_this(_private: Private) {} + | ^^^^^^^ + = note: expected signature `fn(Private)` + found signature `fn(MyPrivate)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/type-alias-impl-trait/unused_generic_param.rs b/tests/ui/type-alias-impl-trait/unused_generic_param.rs new file mode 100644 index 000000000..ad5e4918c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unused_generic_param.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +fn main() {} + +type PartiallyDefined<T> = impl Sized; + +fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> { + 4u32 +} + +type PartiallyDefined2<T> = impl Sized; + +fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> { + 4u32 +} + +fn partially_defined22<T>(_: T) -> PartiallyDefined2<T> { + 4u32 +} diff --git a/tests/ui/type-alias-impl-trait/weird-return-types.rs b/tests/ui/type-alias-impl-trait/weird-return-types.rs new file mode 100644 index 000000000..faad5ee95 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/weird-return-types.rs @@ -0,0 +1,16 @@ +// edition:2018 +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::future::Future; +use std::fmt::Debug; + +type Foo = impl Debug; + +fn f() -> impl Future<Output = Foo> { + async move { 22_u32 } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs new file mode 100644 index 000000000..449e9fbd0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +type FooFn<B> = impl FnOnce(B); + +fn foo<B: Bar>() -> FooFn<B> { + fn mop<B: Bar>(bar: B) { bar.bar() } + mop // NOTE: no function pointer, but function zst item + //~^ ERROR the trait bound `B: Bar` is not satisfied +} + +fn main() { + let boom: FooFn<u32> = unsafe { core::mem::zeroed() }; + boom(42); +} diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr new file mode 100644 index 000000000..e0005489d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/wf-check-fn-def.rs:11:5 + | +LL | mop // NOTE: no function pointer, but function zst item + | ^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `mop` + --> $DIR/wf-check-fn-def.rs:10:15 + | +LL | fn mop<B: Bar>(bar: B) { bar.bar() } + | ^^^ required by this bound in `mop` +help: consider restricting type parameter `B` + | +LL | type FooFn<B: Bar> = impl FnOnce(B); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs new file mode 100644 index 000000000..3b8470e4a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +// build-pass + +trait Bar { + fn bar(&self); +} + +type FooFn<B> = impl FnOnce(B); + +fn foo<B: Bar>() -> FooFn<B> { + fn mop<B: Bar>(bar: B) { bar.bar() } + mop as fn(B) + // function pointers don't have any obligations on them, + // thus the above compiles. It's obviously unsound to just + // procure a `FooFn` from the ether without making sure that + // the pointer is actually legal for all `B` +} + +fn main() { + let boom: FooFn<u32> = unsafe { core::mem::zeroed() }; + boom(42); +} diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.rs b/tests/ui/type-alias-impl-trait/wf_check_closures.rs new file mode 100644 index 000000000..2c70696ff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +type FooFn<B> = impl FnOnce(); + +fn foo<B: Bar>(bar: B) -> FooFn<B> { + move || { bar.bar() } + //~^ ERROR the trait bound `B: Bar` is not satisfied +} + +fn main() { + let boom: FooFn<u32> = unsafe { core::mem::zeroed() }; + boom(); +} diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr new file mode 100644 index 000000000..58ae8617b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/wf_check_closures.rs:10:5 + | +LL | move || { bar.bar() } + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `foo` + --> $DIR/wf_check_closures.rs:9:11 + | +LL | fn foo<B: Bar>(bar: B) -> FooFn<B> { + | ^^^ required by this bound in `foo` +help: consider restricting type parameter `B` + | +LL | type FooFn<B: Bar> = impl FnOnce(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |