diff options
Diffstat (limited to '')
264 files changed, 5366 insertions, 0 deletions
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.rs b/src/test/ui/type-alias-impl-trait/argument-types.rs new file mode 100644 index 000000000..185207b98 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs b/src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs new file mode 100644 index 000000000..703e3e869 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs new file mode 100644 index 000000000..0ade36daf --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs new file mode 100644 index 000000000..3f34b00ec --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr new file mode 100644 index 000000000..e594dc577 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs new file mode 100644 index 000000000..39f785d8c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs new file mode 100644 index 000000000..42f07d49f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auto-trait-leakage.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage.rs new file mode 100644 index 000000000..a1584581e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs new file mode 100644 index 000000000..fc89b0e87 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr new file mode 100644 index 000000000..d7247302d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs new file mode 100644 index 000000000..5fb7a9473 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr new file mode 100644 index 000000000..1e9a45aac --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs b/src/test/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs new file mode 100644 index 000000000..75d20a6fe --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs b/src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs new file mode 100644 index 000000000..e7bca2231 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs b/src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs new file mode 100644 index 000000000..119f7df1f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs b/src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs new file mode 100644 index 000000000..52802dd8f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/bound_reduction.rs b/src/test/ui/type-alias-impl-trait/bound_reduction.rs new file mode 100644 index 000000000..b9b50f0b7 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs new file mode 100644 index 000000000..4d2890b5d --- /dev/null +++ b/src/test/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 non-defining opaque type use +} diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr new file mode 100644 index 000000000..c405b1f6a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/bound_reduction2.rs:16:5 + | +LL | () + | ^^ + | +note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter + --> $DIR/bound_reduction2.rs:9:10 + | +LL | type Foo<V> = impl Trait<V>; + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs new file mode 100644 index 000000000..55b4dc8dc --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr new file mode 100644 index 000000000..8678e9b33 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs new file mode 100644 index 000000000..83d22161e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr new file mode 100644 index 000000000..920eef11d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/closures_in_branches.rs b/src/test/ui/type-alias-impl-trait/closures_in_branches.rs new file mode 100644 index 000000000..7bb490bbe --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr new file mode 100644 index 000000000..48b7946ea --- /dev/null +++ b/src/test/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: _| 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: _| x.len() + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-alias-impl-trait/coherence.rs b/src/test/ui/type-alias-impl-trait/coherence.rs new file mode 100644 index 000000000..98ac215ad --- /dev/null +++ b/src/test/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 cannot implement trait on type alias impl trait + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr new file mode 100644 index 000000000..3ce25d94f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/coherence.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/coherence.rs:14:41 + | +LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here + --> $DIR/coherence.rs:9:30 + | +LL | type AliasOfForeignType<T> = impl LocalTrait; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/collect_hidden_types.rs b/src/test/ui/type-alias-impl-trait/collect_hidden_types.rs new file mode 100644 index 000000000..e78f178e4 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs new file mode 100644 index 000000000..c32174288 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +mod foo { + type Ty<'a> = impl Sized; + fn defining(s: &str) -> Ty<'_> { s } + fn execute(ty: Ty<'_>) -> &str { todo!() } +} + +mod bar { + type Ty<'a> = impl FnOnce() -> &'a str; + fn defining(s: &str) -> Ty<'_> { move || s } + fn execute(ty: Ty<'_>) -> &str { ty() } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs b/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs new file mode 100644 index 000000000..c30608176 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/cross_crate_ice2.rs b/src/test/ui/type-alias-impl-trait/cross_crate_ice2.rs new file mode 100644 index 000000000..3a7e49026 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/cross_inference.rs b/src/test/ui/type-alias-impl-trait/cross_inference.rs new file mode 100644 index 000000000..dafaf40a6 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs new file mode 100644 index 000000000..811832848 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -0,0 +1,8 @@ +// compile-flags: --edition=2021 +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; //~ ERROR unconstrained opaque type + let foo: T = (1u32, 2u32); + let (a, b): (u32, u32) = foo; +} diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr new file mode 100644 index 000000000..03b172e6d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/cross_inference_pattern_bug.rs:5:14 + | +LL | type T = impl Copy; + | ^^^^^^^^^ + | + = note: `T` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs new file mode 100644 index 000000000..328096d44 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -0,0 +1,13 @@ +// known-bug: #96572 +// compile-flags: --edition=2021 --crate-type=lib +// rustc-env:RUST_BACKTRACE=0 + +// tracked in https://github.com/rust-lang/rust/issues/96572 + +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; // error: unconstrained opaque type + let foo: T = (1u32, 2u32); + let (a, b) = foo; // removing this line makes the code compile +} diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr new file mode 100644 index 000000000..8aa1f4956 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/cross_inference_pattern_bug_no_type.rs:10:14 + | +LL | type T = impl Copy; // error: unconstrained opaque type + | ^^^^^^^^^ + | + = note: `T` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_rpit.rs b/src/test/ui/type-alias-impl-trait/cross_inference_rpit.rs new file mode 100644 index 000000000..f6affbf17 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs new file mode 100644 index 000000000..6febd0715 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr new file mode 100644 index 000000000..60bc24320 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs new file mode 100644 index 000000000..5bda5f0fc --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr new file mode 100644 index 000000000..fbfa0ccf1 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/defining-use-submodule.rs b/src/test/ui/type-alias-impl-trait/defining-use-submodule.rs new file mode 100644 index 000000000..8b51f5571 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses.rs new file mode 100644 index 000000000..4505c4d95 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr new file mode 100644 index 000000000..a8b4cd7af --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs new file mode 100644 index 000000000..7740f774e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +// check-pass +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar() -> Foo { + panic!() +} + +fn boo() -> Foo { + loop {} +} diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs new file mode 100644 index 000000000..8549687ea --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs new file mode 100644 index 000000000..4f424b8c6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type OneLifetime<'a, 'b> = impl std::fmt::Debug; + +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/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr new file mode 100644 index 000000000..0c50a84e8 --- /dev/null +++ b/src/test/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:11:5 + | +LL | b + | ^ expected `&'a u32`, got `&'b u32` + | +note: previous use here + --> $DIR/different_lifetimes_defining_uses.rs:7:5 + | +LL | a + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/fallback.rs b/src/test/ui/type-alias-impl-trait/fallback.rs new file mode 100644 index 000000000..d8cf7d71f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/fallback.stderr b/src/test/ui/type-alias-impl-trait/fallback.stderr new file mode 100644 index 000000000..e767bfdb0 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/field-types.rs b/src/test/ui/type-alias-impl-trait/field-types.rs new file mode 100644 index 000000000..d99ed5812 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/future.rs b/src/test/ui/type-alias-impl-trait/future.rs new file mode 100644 index 000000000..56323216e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/future.stderr b/src/test/ui/type-alias-impl-trait/future.stderr new file mode 100644 index 000000000..7e76c120a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs new file mode 100644 index 000000000..8b683ad28 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr new file mode 100644 index 000000000..47ac33462 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs new file mode 100644 index 000000000..c9b9e128f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Two<'a, 'b> = impl std::fmt::Debug; + + +fn one<'a>(t: &'a ()) -> Two<'a, 'a> { + t + //~^ ERROR non-defining opaque type use +} diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr new file mode 100644 index 000000000..222aaea78 --- /dev/null +++ b/src/test/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:9:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_lifetime_param.rs:5:10 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug; + | ^^ ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs new file mode 100644 index 000000000..093c1c231 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type TwoTys<T, U> = impl Debug; + +type TwoLifetimes<'a, 'b> = impl Debug; + +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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr new file mode 100644 index 000000000..b2edcc552 --- /dev/null +++ b/src/test/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:16: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:21:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_param_use.rs:10:19 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:26:5 + | +LL | t + | ^ + | +note: constant used multiple times + --> $DIR/generic_duplicate_param_use.rs:12:16 + | +LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug; + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs new file mode 100644 index 000000000..c17d595db --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs new file mode 100644 index 000000000..201535efe --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr new file mode 100644 index 000000000..3dbfff745 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs new file mode 100644 index 000000000..e7a25fc72 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr new file mode 100644 index 000000000..7bec38220 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs new file mode 100644 index 000000000..d1e5a0f01 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr new file mode 100644 index 000000000..21a5369d9 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs new file mode 100644 index 000000000..3bd1dda63 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr new file mode 100644 index 000000000..2768f0c3a --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Debug` for `(T, U)` +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 because of the requirements on the impl of `Debug` for `(T, U)` +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 because of the requirements on the impl of `Debug` for `(U, T)` +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 because of the requirements on the impl of `Debug` for `(U, T)` +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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs new file mode 100644 index 000000000..5120925e5 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr new file mode 100644 index 000000000..c1712ca2e --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Debug` for `(T, T)` +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 because of the requirements on the impl of `Debug` for `(U, T)` +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 because of the requirements on the impl of `Debug` for `(U, T)` +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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs new file mode 100644 index 000000000..feebf81ee --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs new file mode 100644 index 000000000..3a4b5047b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr new file mode 100644 index 000000000..b83105c45 --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Debug` for `(T, u32)` +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 because of the requirements on the impl of `Debug` for `(U, u32)` +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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs new file mode 100644 index 000000000..6afcdfe4d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr new file mode 100644 index 000000000..50cf98273 --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Debug` for `(A, B, _)` +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 because of the requirements on the impl of `Debug` for `(A, B, _)` +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 because of the requirements on the impl of `Debug` for `(A, B, i32)` +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 because of the requirements on the impl of `Debug` for `(A, B, i32)` +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/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs new file mode 100644 index 000000000..e109c38c9 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Region<'a> = impl std::fmt::Debug; + +fn region<'b>(a: &'b ()) -> Region<'b> { + a +} diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs new file mode 100644 index 000000000..f39741a6a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -0,0 +1,29 @@ +#![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 non-defining opaque type use in defining scope +} + +fn concrete_lifetime() -> OneLifetime<'static> { + 6u32 + //~^ ERROR non-defining opaque type use in defining scope +} + +fn concrete_const() -> OneConst<{ 123 }> { + 7u32 + //~^ ERROR non-defining opaque type use in defining scope +} diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr new file mode 100644 index 000000000..e7565525a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -0,0 +1,35 @@ +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:17:5 + | +LL | 5u32 + | ^^^^ + | +note: used non-generic type `u32` for generic parameter + --> $DIR/generic_nondefining_use.rs:7:12 + | +LL | type OneTy<T> = impl Debug; + | ^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:22: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: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:27:5 + | +LL | 7u32 + | ^^^^ + | +note: used non-generic constant `123` for generic parameter + --> $DIR/generic_nondefining_use.rs:11:15 + | +LL | type OneConst<const X: usize> = impl Debug; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.rs b/src/test/ui/type-alias-impl-trait/generic_not_used.rs new file mode 100644 index 000000000..c70f473cf --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_not_used.stderr b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr new file mode 100644 index 000000000..fd720239a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs new file mode 100644 index 000000000..cb9077647 --- /dev/null +++ b/src/test/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 non-defining opaque type use +} + +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/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr new file mode 100644 index 000000000..ba583241a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -0,0 +1,32 @@ +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: non-defining opaque type use in defining scope + --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + | +LL | let z: i32 = x; + | ^ + | +note: used non-generic type `&'static i32` for generic parameter + --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 + | +LL | type WrongGeneric<T> = impl 'static; + | ^ + +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 + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.rs b/src/test/ui/type-alias-impl-trait/generic_underconstrained.rs new file mode 100644 index 000000000..d87a25aad --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr new file mode 100644 index 000000000..c73288329 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_underconstrained2.rs b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.rs new file mode 100644 index 000000000..8adc0bf32 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr new file mode 100644 index 000000000..d77d978aa --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs new file mode 100644 index 000000000..851c2f66c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr new file mode 100644 index 000000000..8cf8fb1d1 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs new file mode 100644 index 000000000..685d76ee3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr new file mode 100644 index 000000000..b93ea955c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/incomplete-inference.rs b/src/test/ui/type-alias-impl-trait/incomplete-inference.rs new file mode 100644 index 000000000..4c8bf2cfc --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr b/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr new file mode 100644 index 000000000..9a0e71b4e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs new file mode 100644 index 000000000..79caddf79 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr new file mode 100644 index 000000000..b9d646b92 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs new file mode 100644 index 000000000..50eeff0b1 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr new file mode 100644 index 000000000..4c5fd2255 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-52843.rs b/src/test/ui/type-alias-impl-trait/issue-52843.rs new file mode 100644 index 000000000..159d3ccd2 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-52843.stderr b/src/test/ui/type-alias-impl-trait/issue-52843.stderr new file mode 100644 index 000000000..acd40f980 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53092-2.rs b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs new file mode 100644 index 000000000..438ac35fd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs @@ -0,0 +1,15 @@ +#![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| ()) }; +//~^ ERROR: cannot transmute + +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/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr new file mode 100644 index 000000000..1b89d5571 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -0,0 +1,55 @@ +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[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/issue-53092-2.rs:6:41 + | +LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:68]` (0 bits) + = note: target type: `Bug<u8, ()>` (size can vary because of [type error]) + +error[E0277]: the trait bound `U: From<T>` is not satisfied + --> $DIR/issue-53092-2.rs:10: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:9: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 3 previous errors + +Some errors have detailed explanations: E0277, E0391, E0512. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53092.rs b/src/test/ui/type-alias-impl-trait/issue-53092.rs new file mode 100644 index 000000000..1be5b46d6 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53092.stderr b/src/test/ui/type-alias-impl-trait/issue-53092.stderr new file mode 100644 index 000000000..2109cf8a7 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53096.rs b/src/test/ui/type-alias-impl-trait/issue-53096.rs new file mode 100644 index 000000000..007dcf3bc --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53096.stderr b/src/test/ui/type-alias-impl-trait/issue-53096.stderr new file mode 100644 index 000000000..0af3a75f8 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs new file mode 100644 index 000000000..4a11bb502 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr new file mode 100644 index 000000000..d20b1cc6d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -0,0 +1,11 @@ +error[E0275]: overflow evaluating the requirement `fn() -> Foo {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`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs new file mode 100644 index 000000000..9c1cbf926 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53598.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.stderr new file mode 100644 index 000000000..f8b8201e2 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs new file mode 100644 index 000000000..a3f126d56 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr new file mode 100644 index 000000000..eb1c9603a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs new file mode 100644 index 000000000..af0780ab0 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs b/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs new file mode 100644 index 000000000..3a7a5da07 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs new file mode 100644 index 000000000..067ed7ea1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -0,0 +1,27 @@ +// Regression test for issue #57611 +// Ensures that we don't ICE +// FIXME: This should compile, but it currently doesn't +// known-bug: unknown + +#![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/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr new file mode 100644 index 000000000..f14bf6b0f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ one type is more general than the other + | + = note: expected trait `for<'r> Fn<(&'r X,)>` + found trait `Fn<(&X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs new file mode 100644 index 000000000..484589387 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-57700.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.stderr new file mode 100644 index 000000000..31b6df5d4 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs b/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs new file mode 100644 index 000000000..fcab2c7db --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-57961.rs b/src/test/ui/type-alias-impl-trait/issue-57961.rs new file mode 100644 index 000000000..472886c9c --- /dev/null +++ b/src/test/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 type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X +} + +fn incoherent() { + let f: X = 22_i32; +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.stderr b/src/test/ui/type-alias-impl-trait/issue-57961.stderr new file mode 100644 index 000000000..ed4caf6ce --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57961.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X` + --> $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/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs new file mode 100644 index 000000000..f20ddf020 --- /dev/null +++ b/src/test/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<'a> = impl Generator<Return = (), Yield = u64> + 'a; +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/src/test/ui/type-alias-impl-trait/issue-58887.rs b/src/test/ui/type-alias-impl-trait/issue-58887.rs new file mode 100644 index 000000000..96ac78602 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-58951-2.rs b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs new file mode 100644 index 000000000..e4ba7f8e2 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-58951.rs b/src/test/ui/type-alias-impl-trait/issue-58951.rs new file mode 100644 index 000000000..7303cbab4 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs new file mode 100644 index 000000000..9a40f3d9b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr new file mode 100644 index 000000000..082b0f0c3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60407.rs b/src/test/ui/type-alias-impl-trait/issue-60407.rs new file mode 100644 index 000000000..b833429c7 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60407.stderr b/src/test/ui/type-alias-impl-trait/issue-60407.stderr new file mode 100644 index 000000000..fecee2779 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60564-working.rs b/src/test/ui/type-alias-impl-trait/issue-60564-working.rs new file mode 100644 index 000000000..38accc824 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs new file mode 100644 index 000000000..4fc767931 --- /dev/null +++ b/src/test/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 non-defining opaque type use in defining scope + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr new file mode 100644 index 000000000..bbc93657b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-60564.rs:20:9 + | +LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: used non-generic type `u8` for generic parameter + --> $DIR/issue-60564.rs:8:25 + | +LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-60662.rs b/src/test/ui/type-alias-impl-trait/issue-60662.rs new file mode 100644 index 000000000..b9faa668b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-60662.stdout b/src/test/ui/type-alias-impl-trait/issue-60662.stdout new file mode 100644 index 000000000..5b3d7375d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs b/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs new file mode 100644 index 000000000..36779a0ce --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/src/test/ui/type-alias-impl-trait/issue-63263-closure-return.rs new file mode 100644 index 000000000..7414611a7 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-63279.rs b/src/test/ui/type-alias-impl-trait/issue-63279.rs new file mode 100644 index 000000000..97332e16d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr new file mode 100644 index 000000000..110b8d1ee --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs new file mode 100644 index 000000000..7066a0535 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs b/src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs new file mode 100644 index 000000000..28f4a85c9 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs new file mode 100644 index 000000000..9a119c4d2 --- /dev/null +++ b/src/test/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: cannot implement trait on type alias impl trait + +fn bazr() -> Bar { } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr new file mode 100644 index 000000000..41bcea27e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65384.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/issue-65384.rs:10:18 + | +LL | impl MyTrait for Bar {} + | ^^^ + | +note: type alias impl trait defined here + --> $DIR/issue-65384.rs:8:12 + | +LL | type Bar = impl MyTrait; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 000000000..72c22827f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-65918.rs b/src/test/ui/type-alias-impl-trait/issue-65918.rs new file mode 100644 index 000000000..af6d50109 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs b/src/test/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs new file mode 100644 index 000000000..d97270c31 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs new file mode 100644 index 000000000..cd219328a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs new file mode 100644 index 000000000..5223fb1c7 --- /dev/null +++ b/src/test/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 non-defining opaque type use in defining scope + +fn main() {} + +impl<X> Trait<X> for () {} diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr new file mode 100644 index 000000000..7fb9a0c41 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-68368-non-defining-use-2.rs:9:29 + | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + | +note: used non-generic type `()` for generic parameter + --> $DIR/issue-68368-non-defining-use-2.rs:7:16 + | +LL | type Alias<'a, U> = impl Trait<U>; + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs new file mode 100644 index 000000000..b50462bf2 --- /dev/null +++ b/src/test/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 non-defining opaque type use in defining scope + +fn main() {} + +impl Trait<()> for () {} diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr new file mode 100644 index 000000000..8059621b6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-68368-non-defining-use.rs:9:29 + | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + | +note: used non-generic type `()` for generic parameter + --> $DIR/issue-68368-non-defining-use.rs:7:16 + | +LL | type Alias<'a, U> = impl Trait<U>; + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs new file mode 100644 index 000000000..428454bc0 --- /dev/null +++ b/src/test/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 non-defining opaque type use in defining scope + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr new file mode 100644 index 000000000..7b50c8af2 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -0,0 +1,31 @@ +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: non-defining opaque type use in defining scope + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 + | +LL | fn my_fun() -> Return<()> {} + | ^^ + | +note: used non-generic type `()` for generic parameter + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13 + | +LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs new file mode 100644 index 000000000..a6916eda8 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-69323.rs b/src/test/ui/type-alias-impl-trait/issue-69323.rs new file mode 100644 index 000000000..a9bd6daf2 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-70121.rs b/src/test/ui/type-alias-impl-trait/issue-70121.rs new file mode 100644 index 000000000..dff0d89d4 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-72793.rs b/src/test/ui/type-alias-impl-trait/issue-72793.rs new file mode 100644 index 000000000..828c87114 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74244.rs b/src/test/ui/type-alias-impl-trait/issue-74244.rs new file mode 100644 index 000000000..bb4104b3d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74244.stderr b/src/test/ui/type-alias-impl-trait/issue-74244.stderr new file mode 100644 index 000000000..ff6bacd27 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74280.rs b/src/test/ui/type-alias-impl-trait/issue-74280.rs new file mode 100644 index 000000000..ad641eaa0 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74280.stderr b/src/test/ui/type-alias-impl-trait/issue-74280.stderr new file mode 100644 index 000000000..5ed29e0ac --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr new file mode 100644 index 000000000..f15d0a069 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74761.rs b/src/test/ui/type-alias-impl-trait/issue-74761.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-74761.stderr b/src/test/ui/type-alias-impl-trait/issue-74761.stderr new file mode 100644 index 000000000..1d016fe07 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs new file mode 100644 index 000000000..fb56cc54d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -0,0 +1,24 @@ +// Regression test for issue #76202 +// Tests that we don't ICE when we have a trait impl on a TAIT. + +#![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 { + //~^ ERROR cannot implement trait + fn test(self) {} +} + +fn main() { + let x: F = f(); + x.test(); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr new file mode 100644 index 000000000..2d4a6854a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/issue-76202-trait-impl-for-tait.rs:16:15 + | +LL | impl Test for F { + | ^ + | +note: type alias impl trait defined here + --> $DIR/issue-76202-trait-impl-for-tait.rs:9:10 + | +LL | type F = impl Dummy; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.rs b/src/test/ui/type-alias-impl-trait/issue-77179.rs new file mode 100644 index 000000000..8d818d4a3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr new file mode 100644 index 000000000..053546e4b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-78450.rs b/src/test/ui/type-alias-impl-trait/issue-78450.rs new file mode 100644 index 000000000..fccbfb74f --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs new file mode 100644 index 000000000..fa25d8f76 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs @@ -0,0 +1,23 @@ +// 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. + +#![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 () { //~ ERROR cannot implement trait + fn f() { + println!("ho"); + } +} + +fn main() { + <() as TraitArg<Bar>>::f(); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr new file mode 100644 index 000000000..bb70d07be --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/issue-84660-trait-impl-for-tait.rs:15:15 + | +LL | impl TraitArg<Bar> for () { + | ^^^ + | +note: type alias impl trait defined here + --> $DIR/issue-84660-trait-impl-for-tait.rs:8:12 + | +LL | type Bar = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs new file mode 100644 index 000000000..f12d1b6d9 --- /dev/null +++ b/src/test/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 { //~ ERROR cannot implement trait + type Out = Out; + fn convert(_i: In) -> Self::Out { + unreachable!(); + } +} + +impl<In, Out> Trait<(), In> for Out { + 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/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr new file mode 100644 index 000000000..f2d600fb4 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/issue-84660-unsoundness.rs:16:21 + | +LL | impl<In, Out> Trait<Bar, In> for Out { + | ^^^ + | +note: type alias impl trait defined here + --> $DIR/issue-84660-unsoundness.rs:8:12 + | +LL | type Bar = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs new file mode 100644 index 000000000..80a74eb63 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs new file mode 100644 index 000000000..de070fc9d --- /dev/null +++ b/src/test/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 = ()>; + +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/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr new file mode 100644 index 000000000..b636ada8b --- /dev/null +++ b/src/test/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 = ()>; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-89952.rs b/src/test/ui/type-alias-impl-trait/issue-89952.rs new file mode 100644 index 000000000..dc0f19c04 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-90400-1.rs b/src/test/ui/type-alias-impl-trait/issue-90400-1.rs new file mode 100644 index 000000000..8550a3e86 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-90400-1.rs @@ -0,0 +1,30 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(generic_associated_types)] +#![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/src/test/ui/type-alias-impl-trait/issue-90400-1.stderr b/src/test/ui/type-alias-impl-trait/issue-90400-1.stderr new file mode 100644 index 000000000..428a10740 --- /dev/null +++ b/src/test/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:23: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:22: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/src/test/ui/type-alias-impl-trait/issue-90400-2.rs b/src/test/ui/type-alias-impl-trait/issue-90400-2.rs new file mode 100644 index 000000000..2b369bb8a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-90400-2.rs @@ -0,0 +1,38 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(generic_associated_types)] +#![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/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr b/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr new file mode 100644 index 000000000..5da05a439 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/issue-90400-2.rs:26:9 + | +LL | MyBaz(bar) + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required because of the requirements on the impl of `Baz` for `MyBaz<B>` + --> $DIR/issue-90400-2.rs:31:14 + | +LL | impl<B: Bar> Baz for MyBaz<B> { + | ^^^ ^^^^^^^^ +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/src/test/ui/type-alias-impl-trait/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs new file mode 100644 index 000000000..1f8c78926 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-94429.rs b/src/test/ui/type-alias-impl-trait/issue-94429.rs new file mode 100644 index 000000000..2c965b875 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-94429.stderr b/src/test/ui/type-alias-impl-trait/issue-94429.stderr new file mode 100644 index 000000000..8d7f7a07b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/issue-98604.rs b/src/test/ui/type-alias-impl-trait/issue-98604.rs new file mode 100644 index 000000000..a4fd8a82a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-98604.rs @@ -0,0 +1,13 @@ +// 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 type mismatch +} diff --git a/src/test/ui/type-alias-impl-trait/issue-98604.stderr b/src/test/ui/type-alias-impl-trait/issue-98604.stderr new file mode 100644 index 000000000..f04d1b4d7 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-98604.stderr @@ -0,0 +1,18 @@ +error[E0271]: type mismatch resolving `<fn() -> impl Future<Output = ()> {test} as FnOnce<()>>::Output == Pin<Box<(dyn Future<Output = ()> + 'static)>>` + --> $DIR/issue-98604.rs:11: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:7: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/src/test/ui/type-alias-impl-trait/issue-98608.rs b/src/test/ui/type-alias-impl-trait/issue-98608.rs new file mode 100644 index 000000000..d75762a8b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-98608.rs @@ -0,0 +1,9 @@ +fn hi() -> impl Sized { std::ptr::null::<u8>() } + +fn main() { + let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi); + //~^ ERROR type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>` + let boxed = b(); + let null = *boxed; + println!("{null:?}"); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-98608.stderr b/src/test/ui/type-alias-impl-trait/issue-98608.stderr new file mode 100644 index 000000000..8f3ec7d9d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-98608.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>` + --> $DIR/issue-98608.rs:4:39 + | +LL | fn hi() -> impl Sized { std::ptr::null::<u8>() } + | ---------- 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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs new file mode 100644 index 000000000..b887fcf30 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr new file mode 100644 index 000000000..278117009 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs new file mode 100644 index 000000000..3f122f106 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -0,0 +1,9 @@ +#![feature(type_alias_impl_trait)] + +type Foo<'a, 'b> = impl std::fmt::Debug; + +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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr new file mode 100644 index 000000000..81e603e23 --- /dev/null +++ b/src/test/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:6: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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs new file mode 100644 index 000000000..83fd9a1da --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -0,0 +1,21 @@ +// 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) +} + +type Foo<'a, 'b> = impl std::fmt::Debug; + +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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs new file mode 100644 index 000000000..da845e861 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr new file mode 100644 index 000000000..cdaae99e2 --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Into<&'static B>` for `&A` +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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs new file mode 100644 index 000000000..14510a529 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr new file mode 100644 index 000000000..0f752212a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs new file mode 100644 index 000000000..11a922443 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr new file mode 100644 index 000000000..bbe709dcc --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/multiple_definitions.rs b/src/test/ui/type-alias-impl-trait/multiple_definitions.rs new file mode 100644 index 000000000..9e6268e63 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs new file mode 100644 index 000000000..822489716 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr new file mode 100644 index 000000000..62db019ed --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs new file mode 100644 index 000000000..0d7f5bad2 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr new file mode 100644 index 000000000..f4d96038d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs new file mode 100644 index 000000000..ebf3a99bb --- /dev/null +++ b/src/test/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; + +trait Foo<A> { } + +impl Foo<FooX> for () { } +//~^ cannot implement trait on type alias impl trait + +fn foo() -> impl Foo<FooX> { + () +} + +fn main() { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr new file mode 100644 index 000000000..4a3fb1673 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/nested-tait-inference3.rs:10:10 + | +LL | impl Foo<FooX> for () { } + | ^^^^ + | +note: type alias impl trait defined here + --> $DIR/nested-tait-inference3.rs:6:13 + | +LL | type FooX = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs new file mode 100644 index 000000000..6b866be7d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr new file mode 100644 index 000000000..732af5c0b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs new file mode 100644 index 000000000..60b6e1aac --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr new file mode 100644 index 000000000..fa6ecf68d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs new file mode 100644 index 000000000..fed5ac07c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs new file mode 100644 index 000000000..46621362e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -0,0 +1,19 @@ +// 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); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr new file mode 100644 index 000000000..337708b87 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -0,0 +1,20 @@ +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[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/no_inferrable_concrete_type.rs:17:23 + | +LL | let _: foo::Foo = std::mem::transmute(0u8); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Foo` (size can vary because of [type error]) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs new file mode 100644 index 000000000..61153b1e1 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr new file mode 100644 index 000000000..ae03a5b3e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs new file mode 100644 index 000000000..fa47d13f5 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr new file mode 100644 index 000000000..a5ac38c38 --- /dev/null +++ b/src/test/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 because of the requirements on the impl of `Debug` for `(T, i8)` +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 because of the requirements on the impl of `Debug` for `(T, _)` +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/src/test/ui/type-alias-impl-trait/not_well_formed.rs b/src/test/ui/type-alias-impl-trait/not_well_formed.rs new file mode 100644 index 000000000..fbb7a4d58 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/not_well_formed.stderr b/src/test/ui/type-alias-impl-trait/not_well_formed.stderr new file mode 100644 index 000000000..c36b95f47 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/reveal_local.rs b/src/test/ui/type-alias-impl-trait/reveal_local.rs new file mode 100644 index 000000000..7ecb55353 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/reveal_local.stderr b/src/test/ui/type-alias-impl-trait/reveal_local.stderr new file mode 100644 index 000000000..27fded333 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/self-referential-2.rs b/src/test/ui/type-alias-impl-trait/self-referential-2.rs new file mode 100644 index 000000000..8781196c3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr new file mode 100644 index 000000000..2b505d307 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -0,0 +1,23 @@ +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/self-referential-3.rs b/src/test/ui/type-alias-impl-trait/self-referential-3.rs new file mode 100644 index 000000000..d40715717 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/self-referential-4.rs b/src/test/ui/type-alias-impl-trait/self-referential-4.rs new file mode 100644 index 000000000..36742c8ad --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr new file mode 100644 index 000000000..27880f792 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -0,0 +1,63 @@ +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs new file mode 100644 index 000000000..3ff5406a3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr new file mode 100644 index 000000000..97d510f68 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -0,0 +1,66 @@ +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +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 following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs new file mode 100644 index 000000000..748a279e4 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs new file mode 100644 index 000000000..c2ab6a9d1 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr new file mode 100644 index 000000000..dbc183f54 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs new file mode 100644 index 000000000..7cc9ccaab --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr new file mode 100644 index 000000000..61287f268 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs new file mode 100644 index 000000000..f6a830296 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs new file mode 100644 index 000000000..fddecfcac --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs new file mode 100644 index 000000000..5630e036b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs new file mode 100644 index 000000000..857066c78 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr new file mode 100644 index 000000000..a31cf1a51 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs new file mode 100644 index 000000000..07c891f06 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs new file mode 100644 index 000000000..c5e8068e5 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs new file mode 100644 index 000000000..1a4064055 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs new file mode 100644 index 000000000..1f2d0e47e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs new file mode 100644 index 000000000..efbf4f1e3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr new file mode 100644 index 000000000..8cdce2f8e --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs new file mode 100644 index 000000000..e5e7fb677 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr new file mode 100644 index 000000000..a770eeac3 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs new file mode 100644 index 000000000..7c7a1b405 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr new file mode 100644 index 000000000..3f3699ce5 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs new file mode 100644 index 000000000..8ca279eec --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr new file mode 100644 index 000000000..3f7acd338 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs new file mode 100644 index 000000000..70c2ee427 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs new file mode 100644 index 000000000..67f56bcde --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs new file mode 100644 index 000000000..fd954801d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs new file mode 100644 index 000000000..4e9d1788b --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr new file mode 100644 index 000000000..1dabe4586 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs b/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs new file mode 100644 index 000000000..aa537dfc9 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr new file mode 100644 index 000000000..e70916573 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -0,0 +1,19 @@ +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 because of the requirements on the impl of `ProofForConversion<T>` for `()` + --> $DIR/underconstrained_generic.rs:13:16 + | +LL | impl<X: Trait> ProofForConversion<X> for () { + | ^^^^^^^^^^^^^^^^^^^^^ ^^ +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/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs new file mode 100644 index 000000000..c5b2e8a1c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr new file mode 100644 index 000000000..12d85a49d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/unused_generic_param.rs b/src/test/ui/type-alias-impl-trait/unused_generic_param.rs new file mode 100644 index 000000000..ad5e4918c --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/weird-return-types.rs b/src/test/ui/type-alias-impl-trait/weird-return-types.rs new file mode 100644 index 000000000..faad5ee95 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/wf-check-fn-def.rs b/src/test/ui/type-alias-impl-trait/wf-check-fn-def.rs new file mode 100644 index 000000000..449e9fbd0 --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/src/test/ui/type-alias-impl-trait/wf-check-fn-def.stderr new file mode 100644 index 000000000..e0005489d --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs b/src/test/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs new file mode 100644 index 000000000..3b8470e4a --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/wf_check_closures.rs b/src/test/ui/type-alias-impl-trait/wf_check_closures.rs new file mode 100644 index 000000000..2c70696ff --- /dev/null +++ b/src/test/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/src/test/ui/type-alias-impl-trait/wf_check_closures.stderr b/src/test/ui/type-alias-impl-trait/wf_check_closures.stderr new file mode 100644 index 000000000..58ae8617b --- /dev/null +++ b/src/test/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`. |