diff options
Diffstat (limited to 'tests/ui/generic-associated-types')
248 files changed, 6726 insertions, 0 deletions
diff --git a/tests/ui/generic-associated-types/anonymize-bound-vars.rs b/tests/ui/generic-associated-types/anonymize-bound-vars.rs new file mode 100644 index 000000000..eb7a12412 --- /dev/null +++ b/tests/ui/generic-associated-types/anonymize-bound-vars.rs @@ -0,0 +1,13 @@ +// check-pass +// +// regression test for #98702 + +trait Foo { + type Assoc<T>; +} + +impl Foo for () { + type Assoc<T> = [T; 2*2]; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/auxiliary/foo_defn.rs b/tests/ui/generic-associated-types/auxiliary/foo_defn.rs new file mode 100644 index 000000000..21a9b3b89 --- /dev/null +++ b/tests/ui/generic-associated-types/auxiliary/foo_defn.rs @@ -0,0 +1,6 @@ +use std::{future::Future, pin::Pin}; + +pub trait Foo { + type Bar: AsRef<()>; + fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>>; +} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs new file mode 100644 index 000000000..5101de19d --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs @@ -0,0 +1,34 @@ +// check-fail +// known-bug: unknown + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +use std::fmt::Debug; + +pub trait LendingIterator { + type Item<'this> + where + Self: 'this; +} + +pub struct WindowsMut<'x> { + slice: &'x (), +} + +impl<'y> LendingIterator for WindowsMut<'y> { + type Item<'this> = &'this mut () where 'y: 'this; +} + +fn print_items<I>(_iter: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Debug, +{ +} + +fn main() { + let slice = &mut (); + let windows = WindowsMut { slice }; + print_items::<WindowsMut<'_>>(windows); +} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr new file mode 100644 index 000000000..362aeae23 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/hrtb-implied-1.rs:31:22 + | +LL | let slice = &mut (); + | ^^ creates a temporary value which is freed while still in use +LL | let windows = WindowsMut { slice }; +LL | print_items::<WindowsMut<'_>>(windows); + | -------------------------------------- argument requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-1.rs:26:26 + | +LL | for<'a> I::Item<'a>: Debug, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs new file mode 100644 index 000000000..3174227a7 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs @@ -0,0 +1,39 @@ +// check-fail +// known-bug: unknown + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +trait LendingIterator: Sized { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Self::Item<'_>; +} +fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool +where + F: FnMut(I::Item<'_>), +{ + let mut iter2 = Eat(iter, f); + let _next = iter2.next(); + true +} +impl<I: LendingIterator> LendingIterator for &mut I { + type Item<'a> = I::Item<'a> where Self:'a; + fn next(&mut self) -> Self::Item<'_> { + (**self).next() + } +} + +struct Eat<I, F>(I, F); +impl<I: LendingIterator, F> Iterator for Eat<I, F> +where + F: FnMut(I::Item<'_>), +{ + type Item = (); + fn next(&mut self) -> Option<Self::Item> { + None + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr new file mode 100644 index 000000000..1ee270398 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-2.rs:18:17 + | +LL | fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +... +LL | let _next = iter2.next(); + | ^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: requirement occurs because of a mutable reference to `Eat<&mut I, F>` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs new file mode 100644 index 000000000..bc9e6c8ae --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs @@ -0,0 +1,23 @@ +trait LendingIterator { + type Item<'a> + where + Self: 'a; +} + +impl LendingIterator for &str { + type Item<'a> = () where Self:'a; +} + +fn trivial_bound<I>(_: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Sized, +{ +} + +fn fails(iter: &str) { + trivial_bound(iter); + //~^ borrowed data escapes +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr new file mode 100644 index 000000000..c67e02437 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-3.rs:19:5 + | +LL | fn fails(iter: &str) { + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +LL | trivial_bound(iter); + | ^^^^^^^^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-3.rs:14:26 + | +LL | for<'a> I::Item<'a>: Sized, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.rs b/tests/ui/generic-associated-types/bugs/issue-100013.rs new file mode 100644 index 000000000..973c548d7 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-100013.rs @@ -0,0 +1,35 @@ +// check-fail +// known-bug: unknown +// edition: 2021 + +// We really should accept this, but we need implied bounds between the regions +// in a generator interior. + +pub trait FutureIterator { + type Future<'s, 'cx>: Send + where + 's: 'cx; +} + +fn call<I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::<I::Future<'_, '_>>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr new file mode 100644 index 000000000..9db124a81 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr @@ -0,0 +1,78 @@ +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:15:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:16:38 + | +LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:16:34 + | +LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:22:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:21:14 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:21:10 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: lifetime may not live long enough + --> $DIR/issue-100013.rs:23:17 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | async { // a generator checked for autotrait impl `Send` +LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:29:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:28:18 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:28:10 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/generic-associated-types/bugs/issue-80626.rs b/tests/ui/generic-associated-types/bugs/issue-80626.rs new file mode 100644 index 000000000..d6e18010f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-80626.rs @@ -0,0 +1,12 @@ +// check-pass + +trait Allocator { + type Allocated<T>; +} + +enum LinkedList<A: Allocator> { + Head, + Next(A::Allocated<Self>), +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.rs b/tests/ui/generic-associated-types/bugs/issue-87735.rs new file mode 100644 index 000000000..80737a798 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87735.rs @@ -0,0 +1,44 @@ +// check-fail +// known-bug: #87735, #88526 + +// This should pass, but we need an extension of implied bounds (probably). + +pub trait AsRef2 { + type Output<'a> where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a>; +} + +impl<T> AsRef2 for Vec<T> { + type Output<'a> = &'a [T] where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + &self[..] + } +} + +#[derive(Debug)] +struct Foo<T>(T); +#[derive(Debug)] +struct FooRef<'a, U>(&'a [U]); + +impl<'b, T, U> AsRef2 for Foo<T> +where + // * `for<'b, 'c> T: AsRef2<Output<'b> = &'c [U]>>` does not work + // + // * `U` is unconstrained but should be allowed in this context because `Output` is + // an associated type + T: AsRef2<Output<'b> = &'b [U]>, + U: 'b +{ + type Output<'a> = FooRef<'a, U> where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + FooRef(self.0.as_ref2()) + } +} + +fn main() { + let foo = Foo(vec![1, 2, 3]); + dbg!(foo.as_ref2()); +} diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr new file mode 100644 index 000000000..ebe2054ce --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-87735.rs:25:13 + | +LL | impl<'b, T, U> AsRef2 for Foo<T> + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87755.rs b/tests/ui/generic-associated-types/bugs/issue-87755.rs new file mode 100644 index 000000000..cda722d2f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87755.rs @@ -0,0 +1,19 @@ +// check-fail +// known-bug: #87755 + +// This should pass. + +use std::fmt::Debug; + +trait Foo { + type Ass where Self::Ass: Debug; +} + +#[derive(Debug)] +struct Bar; + +impl Foo for Bar { + type Ass = Bar; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87755.stderr b/tests/ui/generic-associated-types/bugs/issue-87755.stderr new file mode 100644 index 000000000..5e94db9b0 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87755.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `<Bar as Foo>::Ass == _` + --> $DIR/issue-87755.rs:16:16 + | +LL | type Ass = Bar; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87803.rs b/tests/ui/generic-associated-types/bugs/issue-87803.rs new file mode 100644 index 000000000..56237e387 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87803.rs @@ -0,0 +1,25 @@ +// check-fail +// known-bug: #87803 + +// This should pass, but using a type alias vs a reference directly +// changes late-bound -> early-bound. + +trait Scanner { + type Input<'a>; + type Token<'a>; + + fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; +} + +struct IdScanner(); + +impl Scanner for IdScanner { + type Input<'a> = &'a str; + type Token<'a> = &'a str; + + fn scan<'a>(&mut self, s : &'a str) -> &'a str { + s + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87803.stderr b/tests/ui/generic-associated-types/bugs/issue-87803.stderr new file mode 100644 index 000000000..fe2abdedb --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87803.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration + --> $DIR/issue-87803.rs:20:12 + | +LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; + | ---- lifetimes in impl do not match this method in trait +... +LL | fn scan<'a>(&mut self, s : &'a str) -> &'a str { + | ^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.rs b/tests/ui/generic-associated-types/bugs/issue-88382.rs new file mode 100644 index 000000000..8f8cc4523 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88382.rs @@ -0,0 +1,29 @@ +// check-fail +// known-bug: #88382 + +// This should pass, but has a missed normalization due to HRTB. + +trait Iterable { + type Iterator<'a> where Self: 'a; + fn iter(&self) -> Self::Iterator<'_>; +} + +struct SomeImplementation(); + +impl Iterable for SomeImplementation { + type Iterator<'a> = std::iter::Empty<usize>; + fn iter(&self) -> Self::Iterator<'_> { + std::iter::empty() + } +} + +fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + f(&mut i.iter()); +} + +fn main() { + do_something(SomeImplementation(), |_| ()); + do_something(SomeImplementation(), test); +} + +fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr new file mode 100644 index 000000000..a9a70bb71 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-88382.rs:26:40 + | +LL | do_something(SomeImplementation(), test); + | ------------ ^^^^ expected due to this + | | + | required by a bound introduced by this call +... +LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} + | ------------------------------------------------- found signature defined here + | + = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty<usize>) -> _` + found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _` +note: required by a bound in `do_something` + --> $DIR/issue-88382.rs:20:48 + | +LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.rs b/tests/ui/generic-associated-types/bugs/issue-88460.rs new file mode 100644 index 000000000..224e696ad --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88460.rs @@ -0,0 +1,29 @@ +// check-fail +// known-bug: #88460 + +// This should pass, but has a missed normalization due to HRTB. + +pub trait Marker {} + +pub trait Trait { + type Assoc<'a>; +} + +fn test<T>(value: T) +where + T: Trait, + for<'a> T::Assoc<'a>: Marker, +{ +} + +impl Marker for () {} + +struct Foo; + +impl Trait for Foo { + type Assoc<'a> = (); +} + +fn main() { + test(Foo); +} diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr new file mode 100644 index 000000000..6612c4b49 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88460.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied + --> $DIR/issue-88460.rs:28:10 + | +LL | test(Foo); + | ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` + | | + | required by a bound introduced by this call + | + = help: the trait `Marker` is implemented for `()` +note: required by a bound in `test` + --> $DIR/issue-88460.rs:15:27 + | +LL | fn test<T>(value: T) + | ---- required by a bound in this +... +LL | for<'a> T::Assoc<'a>: Marker, + | ^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.rs b/tests/ui/generic-associated-types/bugs/issue-88526.rs new file mode 100644 index 000000000..99397744f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88526.rs @@ -0,0 +1,33 @@ +// check-fail +// known-bug: #88526 + +// This should pass, but requires more logic. + +trait A { + type I<'a>; +} + +pub struct TestA<F> +{ + f: F, +} + +impl<F> A for TestA<F> { + type I<'a> = &'a F; +} + +struct TestB<Q, F> +{ + q: Q, + f: F, +} + +impl<'q, Q, I, F> A for TestB<Q, F> +where + Q: A<I<'q> = &'q I>, + F: Fn(I), +{ + type I<'a> = (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr new file mode 100644 index 000000000..56857c655 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-88526.rs:25:13 + | +LL | impl<'q, Q, I, F> A for TestB<Q, F> + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.rs b/tests/ui/generic-associated-types/bugs/issue-91762.rs new file mode 100644 index 000000000..8f2cc4550 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-91762.rs @@ -0,0 +1,28 @@ +// check-fail +// known-bug: unknown + +// We almost certainly want this to pass, but +// it's particularly difficult currently, because we need a way of specifying +// that `<Self::Base as Functor>::With<T> = Self` without using that when we have +// a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky) +// solution. This might be better to just wait for Chalk. + +pub trait Functor { + type With<T>; + + fn fmap<T, U>(this: Self::With<T>) -> Self::With<U>; +} + +pub trait FunctorExt<T>: Sized { + type Base: Functor<With<T> = Self>; + + fn fmap<U>(self) { + let arg: <Self::Base as Functor>::With<T>; + let ret: <Self::Base as Functor>::With<U>; + + arg = self; + ret = <Self::Base as Functor>::fmap(arg); + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.stderr b/tests/ui/generic-associated-types/bugs/issue-91762.stderr new file mode 100644 index 000000000..1272c8b8a --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-91762.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-91762.rs:24:15 + | +LL | ret = <Self::Base as Functor>::fmap(arg); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `fmap` + | +help: consider specifying the generic arguments + | +LL | ret = <Self::Base as Functor>::fmap::<T, U>(arg); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/generic-associated-types/collections-project-default.rs b/tests/ui/generic-associated-types/collections-project-default.rs new file mode 100644 index 000000000..e08aa18cf --- /dev/null +++ b/tests/ui/generic-associated-types/collections-project-default.rs @@ -0,0 +1,70 @@ +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// check that we don't normalize with trait defaults. + +trait Collection<T> { + type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling<U>: Collection<U> = + <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member<T>: Collection<T, Family = Self>; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member<T> = Vec<T>; +} + +impl<T> Collection<T> for Vec<T> { + type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> +where + C: Collection<i32>, +{ + let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res + //~^ ERROR mismatched types +} + +fn use_floatify() { + let a = vec![1i32, 2, 3]; + let c = floatify_sibling(&a); + assert_eq!(Some(&1.0), c.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/tests/ui/generic-associated-types/collections-project-default.stderr b/tests/ui/generic-associated-types/collections-project-default.stderr new file mode 100644 index 000000000..5701017dc --- /dev/null +++ b/tests/ui/generic-associated-types/collections-project-default.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/collections-project-default.rs:58:5 + | +LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> + | ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type +... +LL | res + | ^^^ expected Collection::Sibling, found CollectionFamily::Member + | + = note: expected associated type `<C as Collection<i32>>::Sibling<f32>` + found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/collections.rs b/tests/ui/generic-associated-types/collections.rs new file mode 100644 index 000000000..15f429afb --- /dev/null +++ b/tests/ui/generic-associated-types/collections.rs @@ -0,0 +1,69 @@ +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// run-pass + +trait Collection<T> { + type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling<U>: Collection<U> = + <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member<T>: Collection<T, Family = Self>; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member<T> = Vec<T>; +} + +impl<T> Collection<T> for Vec<T> { + type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32> +where + C: Collection<i32>, +{ + let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res +} + +fn use_floatify() { + let a = vec![1, 2, 3]; + let b = floatify(&a); + assert_eq!(Some(&1.0), b.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/tests/ui/generic-associated-types/collectivity-regression.rs b/tests/ui/generic-associated-types/collectivity-regression.rs new file mode 100644 index 000000000..54154f9d1 --- /dev/null +++ b/tests/ui/generic-associated-types/collectivity-regression.rs @@ -0,0 +1,22 @@ +// Regression test from https://github.com/rust-lang/rust/pull/98109 + +pub trait Get { + type Value<'a> + where + Self: 'a; +} + +fn multiply_at<T>(x: T) +where + for<'a> T: Get<Value<'a> = ()>, +{ + || { + //~^ `T` does not live long enough + // + // FIXME(#98437). This regressed at some point and + // probably should work. + let _x = x; + }; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/collectivity-regression.stderr b/tests/ui/generic-associated-types/collectivity-regression.stderr new file mode 100644 index 000000000..a085096e1 --- /dev/null +++ b/tests/ui/generic-associated-types/collectivity-regression.stderr @@ -0,0 +1,24 @@ +error: `T` does not live long enough + --> $DIR/collectivity-regression.rs:13:5 + | +LL | / || { +LL | | +LL | | // +LL | | // FIXME(#98437). This regressed at some point and +LL | | // probably should work. +LL | | let _x = x; +LL | | }; + | |_____^ + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/collectivity-regression.rs:11:16 + | +LL | for<'a> T: Get<Value<'a> = ()>, + | ^^^^^^^^^^^^^^^^^^^ +help: consider restricting the type parameter to the `'static` lifetime + | +LL | for<'a> T: Get<Value<'a> = ()> + 'static, + | +++++++++ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs new file mode 100644 index 000000000..c5f9a25a6 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Foo::Assoc GAT. + +trait Foo { + type Assoc<const N: usize>; + fn foo(&self) -> Self::Assoc<3>; +} + +impl Foo for () { + type Assoc<const N: usize> = [(); N]; + fn foo(&self) -> Self::Assoc<3> { + [(); 3] + } +} + +fn main() { + assert_eq!(().foo(), [(); 3]); +} diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs new file mode 100644 index 000000000..cd7941ed9 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Foo::Assoc GAT. + +trait Foo { + type Assoc<const N: usize>; + fn foo<const N: usize>(&self) -> Self::Assoc<N>; +} + +impl Foo for () { + type Assoc<const N: usize> = [(); N]; + fn foo<const N: usize>(&self) -> Self::Assoc<N> { + [(); N] + } +} + +fn main() { + assert_eq!(().foo::<10>(), [(); 10]); +} diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs new file mode 100644 index 000000000..db61fc080 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs @@ -0,0 +1,25 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Bar::Assoc GAT. + +trait Bar { + type Assoc<const N: usize>; +} +trait Foo: Bar { + fn foo(&self) -> Self::Assoc<3>; +} + +impl Bar for () { + type Assoc<const N: usize> = [(); N]; +} + +impl Foo for () { + fn foo(&self) -> Self::Assoc<3> { + [(); 3] + } +} + +fn main() { + assert_eq!(().foo(), [(); 3]); +} diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.rs b/tests/ui/generic-associated-types/const_params_have_right_type.rs new file mode 100644 index 000000000..d2cb12697 --- /dev/null +++ b/tests/ui/generic-associated-types/const_params_have_right_type.rs @@ -0,0 +1,10 @@ +trait Trait { + type Foo<const N: u8>; +} + +impl Trait for () { + type Foo<const N: u64> = u32; + //~^ error: type `Foo` has an incompatible generic parameter for trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr new file mode 100644 index 000000000..fdedd3bf5 --- /dev/null +++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr @@ -0,0 +1,16 @@ +error[E0053]: type `Foo` has an incompatible generic parameter for trait `Trait` + --> $DIR/const_params_have_right_type.rs:6:14 + | +LL | trait Trait { + | ----- +LL | type Foo<const N: u8>; + | ----------- expected const parameter of type `u8` +... +LL | impl Trait for () { + | ----------------- +LL | type Foo<const N: u64> = u32; + | ^^^^^^^^^^^^ found const parameter of type `u64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs new file mode 100644 index 000000000..c78a54997 --- /dev/null +++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs @@ -0,0 +1,14 @@ +// Test that correct syntax is used in suggestion to constrain associated type + +trait X { + type Y<T>; +} + +fn f<T: X>(a: T::Y<i32>) { + //~^ HELP consider constraining the associated type `<T as X>::Y<i32>` to `Vec<i32>` + //~| SUGGESTION Y<i32> = Vec<i32>> + let b: Vec<i32> = a; + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr new file mode 100644 index 000000000..96c4330fe --- /dev/null +++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/constraint-assoc-type-suggestion.rs:10:23 + | +LL | let b: Vec<i32> = a; + | -------- ^ expected struct `Vec`, found associated type + | | + | expected due to this + | + = note: expected struct `Vec<i32>` + found associated type `<T as X>::Y<i32>` +help: consider constraining the associated type `<T as X>::Y<i32>` to `Vec<i32>` + | +LL | fn f<T: X<Y<i32> = Vec<i32>>>(a: T::Y<i32>) { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/construct_with_other_type.rs b/tests/ui/generic-associated-types/construct_with_other_type.rs new file mode 100644 index 000000000..5cb07f558 --- /dev/null +++ b/tests/ui/generic-associated-types/construct_with_other_type.rs @@ -0,0 +1,22 @@ +// check-pass + +use std::ops::Deref; + +trait Foo { + type Bar<'a, 'b>; +} + +trait Baz { + type Quux<'a>: Foo where Self: 'a; + + // This weird type tests that we can use universal function call syntax to access the Item on + type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>> where Self: 'a; +} + +impl<T> Baz for T where T: Foo { + type Quux<'a> = T where T: 'a; + + type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static> where T: 'a; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/cross-crate-bounds.rs b/tests/ui/generic-associated-types/cross-crate-bounds.rs new file mode 100644 index 000000000..8934a07fd --- /dev/null +++ b/tests/ui/generic-associated-types/cross-crate-bounds.rs @@ -0,0 +1,32 @@ +// regression test for #73816 +// We handled bounds differently when `feature(generic_associated_types)` was enabled + +// edition:2018 +// aux-build:foo_defn.rs + +extern crate foo_defn; + +use foo_defn::Foo; +use std::{future::Future, pin::Pin}; + +pub struct FooImpl; + +impl Foo for FooImpl { + type Bar = (); + //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied + fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>> { + panic!() + } +} + +async fn foo() { + bar(&FooImpl).await; +} + +async fn bar<F: Foo>(foo: &F) { + foo.foo().await.as_ref(); +} + +fn main() { + // futures::executor::block_on(foo()); +} diff --git a/tests/ui/generic-associated-types/cross-crate-bounds.stderr b/tests/ui/generic-associated-types/cross-crate-bounds.stderr new file mode 100644 index 000000000..83ee04d5a --- /dev/null +++ b/tests/ui/generic-associated-types/cross-crate-bounds.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): AsRef<()>` is not satisfied + --> $DIR/cross-crate-bounds.rs:15:16 + | +LL | type Bar = (); + | ^^ the trait `AsRef<()>` is not implemented for `()` + | +note: required by a bound in `foo_defn::Foo::Bar` + --> $DIR/auxiliary/foo_defn.rs:4:15 + | +LL | type Bar: AsRef<()>; + | ^^^^^^^^^ required by this bound in `Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/elided-in-expr-position.rs b/tests/ui/generic-associated-types/elided-in-expr-position.rs new file mode 100644 index 000000000..e40093305 --- /dev/null +++ b/tests/ui/generic-associated-types/elided-in-expr-position.rs @@ -0,0 +1,37 @@ +#![allow(unused)] + +pub trait Trait { + type Assoc<'a> where Self: 'a; + + fn f(&self) -> Self::Assoc<'_>; + + // Disallow elision in return position, for now + fn g(&self) -> Self::Assoc; + //~^ ERROR missing generics for associated type `Trait::Assoc` +} + +pub struct Struct { + item: f32 +} + +pub struct GenericStruct<'a> { + ref_item: &'a f32 +} + +impl Trait for Struct { + type Assoc<'a> = GenericStruct<'a>; + + fn f(&self) -> Self::Assoc<'_> { + Self::Assoc { + ref_item: &self.item + } + } + + // Disallow elision in return position, for now + fn g(&self) -> Self::Assoc { + //~^ ERROR missing generics for associated type `Trait::Assoc` + todo!() + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/elided-in-expr-position.stderr b/tests/ui/generic-associated-types/elided-in-expr-position.stderr new file mode 100644 index 000000000..842b23bd4 --- /dev/null +++ b/tests/ui/generic-associated-types/elided-in-expr-position.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `Trait::Assoc` + --> $DIR/elided-in-expr-position.rs:9:26 + | +LL | fn g(&self) -> Self::Assoc; + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/elided-in-expr-position.rs:4:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'_>; + | ++++ + +error[E0107]: missing generics for associated type `Trait::Assoc` + --> $DIR/elided-in-expr-position.rs:31:26 + | +LL | fn g(&self) -> Self::Assoc { + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/elided-in-expr-position.rs:4:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'_> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/empty_generics.rs b/tests/ui/generic-associated-types/empty_generics.rs new file mode 100644 index 000000000..964c2972d --- /dev/null +++ b/tests/ui/generic-associated-types/empty_generics.rs @@ -0,0 +1,6 @@ +trait Foo { + type Bar<,>; + //~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/empty_generics.stderr b/tests/ui/generic-associated-types/empty_generics.stderr new file mode 100644 index 000000000..b753181cf --- /dev/null +++ b/tests/ui/generic-associated-types/empty_generics.stderr @@ -0,0 +1,13 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/empty_generics.rs:2:14 + | +LL | trait Foo { + | - while parsing this item list starting here +LL | type Bar<,>; + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs new file mode 100644 index 000000000..fcc2da801 --- /dev/null +++ b/tests/ui/generic-associated-types/equality-bound.rs @@ -0,0 +1,15 @@ +fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses +//~| ERROR failed to resolve: use of undeclared type `I` + panic!() +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr new file mode 100644 index 000000000..d78f7a7fb --- /dev/null +++ b/tests/ui/generic-associated-types/equality-bound.stderr @@ -0,0 +1,43 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:1:51 + | +LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { +LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:5:41 + | +LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { +LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information + +error[E0433]: failed to resolve: use of undeclared type `I` + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { + | ^ use of undeclared type `I` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr new file mode 100644 index 000000000..614c4a34c --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator.rs:13:45 + | +LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs new file mode 100644 index 000000000..247761dd0 --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -0,0 +1,38 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator<A>: Sized { + fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; +} + +impl<A> FromLendingIterator<A> for Vec<A> { + fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'z> + where + Self: 'z; + fn next(&mut self) -> Option<Self::Item<'_>>; + + fn collect<A, B: FromLendingIterator<A>>(self) -> B + where + Self: Sized, + Self: for<'q> LendingIterator<Item<'q> = A>, + { + <B as FromLendingIterator<A>>::from_iter(self) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr new file mode 100644 index 000000000..f6b0b644e --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator_2.rs:13:45 + | +LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs new file mode 100644 index 000000000..eb9c0456a --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -0,0 +1,30 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator<A>: Sized { + fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; +} + +impl<A> FromLendingIterator<A> for Vec<A> { + fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Option<Self::Item<'_>>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs new file mode 100644 index 000000000..86b164ba7 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -0,0 +1,9 @@ +trait X { + type Y<'x>; +} + +fn main() { + fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + //~^ ERROR: use of undeclared lifetime name `'x` + //~| ERROR: binding for associated type `Y` references lifetime +} diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr new file mode 100644 index 000000000..b77f10084 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr @@ -0,0 +1,26 @@ +error[E0261]: use of undeclared lifetime name `'x` + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:6:35 + | +LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + | ^^ 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 `'x` lifetime + | +LL | fn _f(arg : Box<dyn for<'x, 'a> X<Y<'x> = &'a [u32]>>) {} + | +++ +help: consider introducing lifetime `'x` here + | +LL | fn _f<'x>(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + | ++++ + +error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:6:33 + | +LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0582. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr new file mode 100644 index 000000000..fd54faaf3 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:26:17 + | +LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/gat-in-trait-path.rs:10:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs new file mode 100644 index 000000000..c55f5a726 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -0,0 +1,33 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(associated_type_defaults)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait Foo { + type A<'a> where Self: 'a; +} + +struct Fooy; + +impl Foo for Fooy { + type A<'a> = &'a (); +} + +#[derive(Clone)] +struct Fooer<T>(T); + +impl<T> Foo for Fooer<T> { + type A<'x> = &'x () where T: 'x; +} + +fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} +//[base]~^ the trait `Foo` cannot be made into an object + + +fn main() { + let foo = Fooer(5); + f(Box::new(foo)); +} diff --git a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs new file mode 100644 index 000000000..d00c036fb --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -0,0 +1,14 @@ +trait Foo { + type F<'a>; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T, T1> Foo for T { + //~^ ERROR: the type parameter `T1` is not constrained + type F<T1> = &[u8]; + //~^ ERROR: the name `T1` is already used for + //~| ERROR: `&` without an explicit lifetime name cannot be used here +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr new file mode 100644 index 000000000..cb2b9f32b --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -0,0 +1,25 @@ +error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters + --> $DIR/gat-trait-path-generic-type-arg.rs:9:12 + | +LL | impl <T, T1> Foo for T { + | -- first use of `T1` +LL | +LL | type F<T1> = &[u8]; + | ^^ already used + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/gat-trait-path-generic-type-arg.rs:9:18 + | +LL | type F<T1> = &[u8]; + | ^ explicit lifetime name needed here + +error[E0207]: the type parameter `T1` is not constrained by the impl trait, self type, or predicates + --> $DIR/gat-trait-path-generic-type-arg.rs:7:10 + | +LL | impl <T, T1> Foo for T { + | ^^ unconstrained type parameter + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0207, E0403, E0637. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs new file mode 100644 index 000000000..83b86f04a --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -0,0 +1,15 @@ +trait X { + type Y<'a>; + + fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } +} + +impl<T> X for T { + fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> { + //~^ ERROR missing generics for associated type + //~^^ ERROR missing generics for associated type + t + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr new file mode 100644 index 000000000..499221637 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 + | +LL | fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> { + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> { + | ++++ + +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 + | +LL | fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> { + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs new file mode 100644 index 000000000..9eb069637 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -0,0 +1,16 @@ +trait X { + type Y<'a>; +} + +fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + //~^ ERROR: lifetime in trait object type must be followed by `+` + //~| ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + + +fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} + //~^ ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr new file mode 100644 index 000000000..165779796 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -0,0 +1,74 @@ +error: lifetime in trait object type must be followed by `+` + --> $DIR/gat-trait-path-parenthesised-args.rs:5:29 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^^ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^^^^^ + | +help: use angle brackets instead + | +LL | fn foo<'a>(arg: Box<dyn X<Y<'a> = &'a ()>>) {} + | ~ ~ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:12:27 + | +LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} + | ^-- + | | + | help: remove these parentheses + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^---- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:12:27 + | +LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {} + | ++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/generic-associated-type-bounds.rs b/tests/ui/generic-associated-types/generic-associated-type-bounds.rs new file mode 100644 index 000000000..fdc5a7267 --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-type-bounds.rs @@ -0,0 +1,32 @@ +// run-pass + +pub trait X { + type Y<'a> where Self: 'a; + fn m(&self) -> Self::Y<'_>; +} + +impl X for () { + type Y<'a> = &'a (); + + fn m(&self) -> Self::Y<'_> { + self + } +} + +fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &() { + x.m() +} + +fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &() { + x.m() +} + +fn h(x: &()) -> &() { + x.m() +} + +fn main() { + f(&()); + g(&()); + h(&()); +} diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.rs b/tests/ui/generic-associated-types/generic-associated-types-where.rs new file mode 100644 index 000000000..bbdfffafe --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-types-where.rs @@ -0,0 +1,26 @@ +// Checking the interaction with this other feature +#![feature(associated_type_defaults)] + +use std::fmt::{Display, Debug}; + +trait Foo { + type Assoc where Self: Sized; + type Assoc2<T> where T: Display; + type Assoc3<T>; + type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator<Item=T>; + type NoGenerics; +} + +struct Bar; + +impl Foo for Bar { + type Assoc = usize; + type Assoc2<T> = Vec<T>; + //~^ ERROR `T` doesn't implement `std::fmt::Display` + type Assoc3<T> = Vec<T> where T: Iterator; + //~^ ERROR impl has stricter requirements than trait + type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>; + type NoGenerics = ::std::cell::Cell<i32>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr new file mode 100644 index 000000000..9a745c099 --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr @@ -0,0 +1,25 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/generic-associated-types-where.rs:18:22 + | +LL | type Assoc2<T> = Vec<T>; + | ^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting type parameter `T` + | +LL | type Assoc2<T: std::fmt::Display> = Vec<T>; + | +++++++++++++++++++ + +error[E0276]: impl has stricter requirements than trait + --> $DIR/generic-associated-types-where.rs:20:38 + | +LL | type Assoc3<T>; + | -------------- definition of `Assoc3` from trait +... +LL | type Assoc3<T> = Vec<T> where T: Iterator; + | ^^^^^^^^ impl has extra requirement `T: Iterator` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs new file mode 100644 index 000000000..2cb218bf8 --- /dev/null +++ b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -0,0 +1,13 @@ +use std::ops::Deref; + +trait Iterable { + type Item<'a>; + type Iter<'a>: Iterator<Item = Self::Item<'a>> + + Deref<Target = Self::Item<'b>>; + //~^ ERROR undeclared lifetime + + fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; + //~^ ERROR undeclared lifetime +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr new file mode 100644 index 000000000..396ff15ab --- /dev/null +++ b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -0,0 +1,38 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:6:37 + | +LL | + Deref<Target = Self::Item<'b>>; + | ^^ 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 `'b` lifetime + | +LL | + for<'b> Deref<Target = Self::Item<'b>>; + | +++++++ +help: consider introducing lifetime `'b` here + | +LL | type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>> + | +++ +help: consider introducing lifetime `'b` here + | +LL | trait Iterable<'b> { + | ++++ + +error[E0261]: use of undeclared lifetime name `'undeclared` + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:9:41 + | +LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; + | ^^^^^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'undeclared` here + | +LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>; + | ++++++++++++ +help: consider introducing lifetime `'undeclared` here + | +LL | trait Iterable<'undeclared> { + | +++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/impl_bounds.rs b/tests/ui/generic-associated-types/impl_bounds.rs new file mode 100644 index 000000000..e45bdcf92 --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds.rs @@ -0,0 +1,24 @@ +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a> where Self: 'a; + type B<'a, 'b> where 'a: 'b; + type C where Self: Clone; + fn d() where Self: Clone; +} + +#[derive(Copy, Clone)] +struct Fooy<T>(T); + +impl<T> Foo for Fooy<T> { + type A<'a> = (&'a ()) where Self: 'static; + //~^ ERROR impl has stricter requirements than trait + type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + //~^ ERROR impl has stricter requirements than trait + type C = String where Self: Copy; + //~^ ERROR the trait bound `T: Copy` is not satisfied + fn d() where Self: Copy {} + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr new file mode 100644 index 000000000..261070d1d --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -0,0 +1,77 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:14:39 + | +LL | type A<'a> where Self: 'a; + | ---------- definition of `A` from trait +... +LL | type A<'a> = (&'a ()) where Self: 'static; + | ^^^^^^^ impl has extra requirement `T: 'static` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:16:48 + | +LL | type B<'a, 'b> where 'a: 'b; + | -------------- definition of `B` from trait +... +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + | ^^ impl has extra requirement `'b: 'a` + | +help: copy the `where` clause predicates from the trait + | +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'a: 'b; + | ~~~~~~~~~~~~ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/impl_bounds.rs:18:33 + | +LL | type C = String where Self: Copy; + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required for `Fooy<T>` to implement `Copy` + --> $DIR/impl_bounds.rs:10:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: the requirement `Fooy<T>: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type + --> $DIR/impl_bounds.rs:6:10 + | +LL | trait Foo { + | --- in this trait +... +LL | type C where Self: Clone; + | ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> Foo for Fooy<T> { + | +++++++++++++++++++ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/impl_bounds.rs:20:24 + | +LL | fn d() where Self: Copy {} + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required for `Fooy<T>` to implement `Copy` + --> $DIR/impl_bounds.rs:10:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: the requirement `Fooy<T>: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method + --> $DIR/impl_bounds.rs:7:8 + | +LL | trait Foo { + | --- in this trait +... +LL | fn d() where Self: Clone; + | ^ this trait's method doesn't have the requirement `Fooy<T>: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> Foo for Fooy<T> { + | +++++++++++++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/impl_bounds_ok.rs b/tests/ui/generic-associated-types/impl_bounds_ok.rs new file mode 100644 index 000000000..88f829ea2 --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds_ok.rs @@ -0,0 +1,29 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a> where Self: 'a; + type B<'a, 'b> where 'a: 'b; + type C where Self: Clone; +} + +#[derive(Clone)] +struct Fooy; + +impl Foo for Fooy { + type A<'a> = (&'a ()); + type B<'a: 'b, 'b> = (&'a(), &'b ()); + type C = String; +} + +#[derive(Clone)] +struct Fooer<T>(T); + +impl<T> Foo for Fooer<T> { + type A<'x> = (&'x ()) where T: 'x; + type B<'u, 'v> = (&'v &'u ()) where 'u: 'v; + type C = String where Self: Clone + ToOwned; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-101020.rs b/tests/ui/generic-associated-types/issue-101020.rs new file mode 100644 index 000000000..80d0fa5ad --- /dev/null +++ b/tests/ui/generic-associated-types/issue-101020.rs @@ -0,0 +1,35 @@ +pub trait LendingIterator { + type Item<'a> + where + Self: 'a; + + fn consume<F>(self, _f: F) + where + Self: Sized, + for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>, + { + } +} + +impl<I: LendingIterator + ?Sized> LendingIterator for &mut I { + type Item<'a> = I::Item<'a> where Self: 'a; +} +struct EmptyIter; +impl LendingIterator for EmptyIter { + type Item<'a> = &'a mut () where Self:'a; +} +pub trait FuncInput<'a, F> +where + F: Foo<Self>, + Self: Sized, +{ +} +impl<'a, T, F: 'a> FuncInput<'a, F> for T where F: Foo<T> {} +trait Foo<T> {} + +fn map_test() { + (&mut EmptyIter).consume(()); + //~^ ERROR the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr new file mode 100644 index 000000000..1f9273a8c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-101020.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied + --> $DIR/issue-101020.rs:31:22 + | +LL | (&mut EmptyIter).consume(()); + | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` + | +note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>` + --> $DIR/issue-101020.rs:27:20 + | +LL | impl<'a, T, F: 'a> FuncInput<'a, F> for T where F: Foo<T> {} + | ^^^^^^^^^^^^^^^^ ^ ------ unsatisfied trait bound introduced here +note: required by a bound in `LendingIterator::consume` + --> $DIR/issue-101020.rs:9:33 + | +LL | fn consume<F>(self, _f: F) + | ------- required by a bound in this +... +LL | for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `LendingIterator::consume` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-102114.rs b/tests/ui/generic-associated-types/issue-102114.rs new file mode 100644 index 000000000..de31737ef --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102114.rs @@ -0,0 +1,16 @@ +trait A { + type B<'b>; + fn a() -> Self::B<'static>; +} + +struct C; + +struct Wrapper<T>(T); + +impl A for C { + type B<T> = Wrapper<T>; + //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters + fn a() -> Self::B<'static> {} +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102114.stderr b/tests/ui/generic-associated-types/issue-102114.stderr new file mode 100644 index 000000000..8e41dee54 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102114.stderr @@ -0,0 +1,12 @@ +error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/issue-102114.rs:11:12 + | +LL | type B<'b>; + | -- expected 0 type parameters +... +LL | type B<T> = Wrapper<T>; + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/issue-102333.rs b/tests/ui/generic-associated-types/issue-102333.rs new file mode 100644 index 000000000..6c7256332 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102333.rs @@ -0,0 +1,15 @@ +// check-pass + +trait A { + type T: B<U<1i32> = ()>; +} + +trait B { + type U<const C: i32>; +} + +fn f<T: A>() { + let _: <<T as A>::T as B>::U<1i32> = (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.rs b/tests/ui/generic-associated-types/issue-102335-gat.rs new file mode 100644 index 000000000..a7255fdcb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102335-gat.rs @@ -0,0 +1,12 @@ +trait T { + type A: S<C<(), i32 = ()> = ()>; + //~^ ERROR associated type bindings are not allowed here +} + +trait Q {} + +trait S { + type C<T>: Q; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr new file mode 100644 index 000000000..7a7900a1e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-gat.rs:2:21 + | +LL | type A: S<C<(), i32 = ()> = ()>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/generic-associated-types/issue-47206-where-clause.rs b/tests/ui/generic-associated-types/issue-47206-where-clause.rs new file mode 100644 index 000000000..3d1b88ddf --- /dev/null +++ b/tests/ui/generic-associated-types/issue-47206-where-clause.rs @@ -0,0 +1,14 @@ +// Check that this program doesn't cause the compiler to error without output. + +trait Foo { + type Assoc3<T>; +} + +struct Bar; + +impl Foo for Bar { + type Assoc3<T> = Vec<T> where T: Iterator; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-47206-where-clause.stderr b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr new file mode 100644 index 000000000..7006744df --- /dev/null +++ b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-47206-where-clause.rs:10:38 + | +LL | type Assoc3<T>; + | -------------- definition of `Assoc3` from trait +... +LL | type Assoc3<T> = Vec<T> where T: Iterator; + | ^^^^^^^^ impl has extra requirement `T: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs b/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs new file mode 100644 index 000000000..625ccfe89 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Cert { + type PublicKey<'a>: From<&'a [u8]>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs new file mode 100644 index 000000000..c1140bff8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -0,0 +1,11 @@ +// check-pass + +trait Iterator { + type Item<'a>: 'a; +} + +impl Iterator for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67424.rs b/tests/ui/generic-associated-types/issue-67424.rs new file mode 100644 index 000000000..b6c7c70cd --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67424.rs @@ -0,0 +1,12 @@ +// check-pass +// Fixed by #67160 + +trait Trait1 { + type A; +} + +trait Trait2 { + type Type1<B>: Trait1<A=B>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr new file mode 100644 index 000000000..4cc68530e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:12:23 + | +LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-67510-pass.rs:9:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs new file mode 100644 index 000000000..66ce3e807 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.rs @@ -0,0 +1,15 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait X { + type Y<'a>; +} + +fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} +//[base]~^ ERROR the trait `X` cannot be made into an object + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510.rs b/tests/ui/generic-associated-types/issue-67510.rs new file mode 100644 index 000000000..ab5c25d74 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510.rs @@ -0,0 +1,10 @@ +trait X { + type Y<'a>; +} + +fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {} +//~^ ERROR: use of undeclared lifetime name `'a` +//~| ERROR: use of undeclared lifetime name `'a` +//~| ERROR: the trait `X` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510.stderr b/tests/ui/generic-associated-types/issue-67510.stderr new file mode 100644 index 000000000..d25c5b0f3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510.stderr @@ -0,0 +1,50 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:5:21 + | +LL | fn f(x: Box<dyn X<Y<'a> = &'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 | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {} + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {} + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:5:28 + | +LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {} + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {} + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {} + | ++++ + +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510.rs:5:13 + | +LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-67510.rs:2:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0261. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs new file mode 100644 index 000000000..f1e779fcb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -0,0 +1,29 @@ +// Regression test for #68641 + +trait UnsafeCopy { + type Item<'a>: Copy; + + fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> { + *item + } +} + +impl<T> UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let mut s = String::from("Hello world!"); + + let copy = String::copy(&s); + + // Do we indeed point to the samme memory? + assert!(s.as_ptr() == copy.as_ptr()); + + // Any use of `copy` is certeinly UB after this + drop(s); + + // UB UB UB UB UB!! + println!("{}", copy); +} diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr new file mode 100644 index 000000000..6bb7492af --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-68641-check-gat-bounds.rs:12:21 + | +LL | type Item<'a> = T; + | ^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `UnsafeCopy::Item` + --> $DIR/issue-68641-check-gat-bounds.rs:4:20 + | +LL | type Item<'a>: Copy; + | ^^^^ required by this bound in `UnsafeCopy::Item` +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> UnsafeCopy for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs new file mode 100644 index 000000000..f5502adee --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -0,0 +1,18 @@ +// Regression test for #68642 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl<T> Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + <fn() -> usize>::callme(|| 1); +} diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr new file mode 100644 index 000000000..07452137b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68642-broken-llvm-ir.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68642-broken-llvm-ir.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.rs b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs new file mode 100644 index 000000000..6050a8bf5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -0,0 +1,18 @@ +// Regression test for #68643 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl<T> Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +pub fn main() { + <fn()>::callme(|| {}); +} diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr new file mode 100644 index 000000000..31ded5dab --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68643-broken-mir.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68643-broken-mir.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs new file mode 100644 index 000000000..898cfa1e7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -0,0 +1,18 @@ +// Regression test for #68644 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl<T> Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + <u8>::callme(0); +} diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr new file mode 100644 index 000000000..e2f9930cc --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68644-codegen-selection.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68644-codegen-selection.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs new file mode 100644 index 000000000..60b065bfc --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -0,0 +1,18 @@ +// Regression test for #68645 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl<T> Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + <&dyn Iterator<Item = u8>>::callme(&std::iter::once(1)); +} diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr new file mode 100644 index 000000000..0065368ad --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68645-codegen-fulfillment.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68645-codegen-fulfillment.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68648-1.rs b/tests/ui/generic-associated-types/issue-68648-1.rs new file mode 100644 index 000000000..0df41bab3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-1.rs @@ -0,0 +1,22 @@ +// check-pass + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: for<'b> Fun<F<'b> = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68648-2.rs b/tests/ui/generic-associated-types/issue-68648-2.rs new file mode 100644 index 000000000..0f963d58f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-2.rs @@ -0,0 +1,21 @@ +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + T::identity(()) + //~^ ERROR: mismatched types +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68648-2.stderr b/tests/ui/generic-associated-types/issue-68648-2.stderr new file mode 100644 index 000000000..b2bef19eb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-2.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-68648-2.rs:12:17 + | +LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + | - this type parameter +LL | T::identity(()) + | ----------- ^^ expected type parameter `T`, found `()` + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found unit type `()` +note: associated function defined here + --> $DIR/issue-68648-2.rs:4:8 + | +LL | fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } + | ^^^^^^^^ -------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-68649-pass.rs b/tests/ui/generic-associated-types/issue-68649-pass.rs new file mode 100644 index 000000000..772743877 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68649-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68653.rs b/tests/ui/generic-associated-types/issue-68653.rs new file mode 100644 index 000000000..170b87cf2 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68653.rs @@ -0,0 +1,13 @@ +// A regression test for #68653, which was fixed by #68938. + +// check-pass + +trait Fun { + type F<'a: 'a>; +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.rs b/tests/ui/generic-associated-types/issue-68656-unsized-values.rs new file mode 100644 index 000000000..607cfed0b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -0,0 +1,19 @@ +// Regression test for #68656 + +trait UnsafeCopy<T: Copy> { + type Item<'a>: std::ops::Deref<Target = T>; + + fn bug<'a>(item: &Self::Item<'a>) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T { + type Item<'a> = T; + //~^ ERROR type mismatch resolving `<T as Deref>::Target == T` +} + +fn main() { + <&'static str>::bug(&""); +} diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr new file mode 100644 index 000000000..e8770aedf --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -0,0 +1,23 @@ +error[E0271]: type mismatch resolving `<T as Deref>::Target == T` + --> $DIR/issue-68656-unsized-values.rs:13:21 + | +LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T { + | - this type parameter +LL | type Item<'a> = T; + | ^ expected type parameter `T`, found associated type + | + = note: expected type parameter `T` + found associated type `<T as Deref>::Target` +note: required by a bound in `UnsafeCopy::Item` + --> $DIR/issue-68656-unsized-values.rs:4:36 + | +LL | type Item<'a>: std::ops::Deref<Target = T>; + | ^^^^^^^^^^ required by this bound in `UnsafeCopy::Item` +help: consider further restricting this bound + | +LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<T> for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-70303.rs b/tests/ui/generic-associated-types/issue-70303.rs new file mode 100644 index 000000000..0edff5e4e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70303.rs @@ -0,0 +1,57 @@ +// check-pass + +trait Document { + type Cursor<'a>: DocCursor<'a> where Self: 'a; + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { + document: &self, + } + } +} + + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document<Cursor<'d> = Cursor>, + { + Lexer { + cursor: document.cursor(), + _phantom: std::marker::PhantomData, + } + } +} + +pub fn main() { + let doc = DocumentImpl {}; + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs new file mode 100644 index 000000000..8898d4c7d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -0,0 +1,55 @@ +trait Document { + type Cursor<'a>: DocCursor<'a>; + //~^ ERROR: missing required bound on `Cursor` + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { document: &self } + } +} + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document<Cursor<'d> = Cursor>, + { + Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData } + } +} + +fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + //~^ ERROR `'_` cannot be used here [E0637] + //~| ERROR: missing lifetime specifier + DocumentImpl {} +} + +pub fn main() { + let doc = create_doc(); + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr new file mode 100644 index 000000000..99339e968 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -0,0 +1,33 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-70304.rs:46:41 + | +LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + | ^^ `'_` is a reserved lifetime name + +error[E0106]: missing lifetime specifier + --> $DIR/issue-70304.rs:46:61 + | +LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'static>> { + | ~~~~~~~ + +error: missing required bound on `Cursor` + --> $DIR/issue-70304.rs:2:5 + | +LL | type Cursor<'a>: DocCursor<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs new file mode 100644 index 000000000..f0e162d82 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -0,0 +1,18 @@ +trait Provider { + type A<'a>; +} + +impl Provider for () { + type A<'a> = (); +} + +struct Holder<B> { + inner: Box<dyn Provider<A = B>>, + //~^ ERROR: missing generics for associated type +} + +fn main() { + Holder { + inner: Box::new(()), + }; +} diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr new file mode 100644 index 000000000..4b4fe43e8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:10:27 + | +LL | inner: Box<dyn Provider<A = B>>, + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-71176.rs:2:10 + | +LL | type A<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | inner: Box<dyn Provider<A<'a> = B>>, + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-74684-1.rs b/tests/ui/generic-associated-types/issue-74684-1.rs new file mode 100644 index 000000000..e9ec80074 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-1.rs @@ -0,0 +1,23 @@ +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = [u8]; +} + +fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> { + let a = [0; 1]; + let _x = T::identity(&a); + //~^ ERROR: `a` does not live long enough + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); +} diff --git a/tests/ui/generic-associated-types/issue-74684-1.stderr b/tests/ui/generic-associated-types/issue-74684-1.stderr new file mode 100644 index 000000000..cacc97307 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-1.stderr @@ -0,0 +1,18 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-1.rs:13:26 + | +LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; +LL | let _x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.rs b/tests/ui/generic-associated-types/issue-74684-2.rs new file mode 100644 index 000000000..ff243af2c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-2.rs @@ -0,0 +1,23 @@ +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = i32; +} + +fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { + let a = [0; 1]; + let x = T::identity(&a); + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); + //~^ ERROR: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` +} diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr new file mode 100644 index 000000000..59b85abf5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + --> $DIR/issue-74684-2.rs:21:9 + | +LL | bug(Box::new(x)); + | --- ^^^^^^^^^^^ type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + | | + | required by a bound introduced by this call + | +note: expected this to be `[u8]` + --> $DIR/issue-74684-2.rs:8:18 + | +LL | type F<'a> = i32; + | ^^^ +note: required by a bound in `bug` + --> $DIR/issue-74684-2.rs:11:28 + | +LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { + | ^^^^^^^^^^^^ required by this bound in `bug` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-74816.rs b/tests/ui/generic-associated-types/issue-74816.rs new file mode 100644 index 000000000..344afb87f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74816.rs @@ -0,0 +1,21 @@ +#![feature(associated_type_defaults)] + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + type Associated: Trait1 = Self; + //~^ ERROR: the trait bound `Self: Trait1` is not satisfied + //~| the size for values of type `Self` cannot be known +} + +impl Trait2 for () {} + +fn call_foo<T: Trait2>() { + T::Associated::foo() +} + +fn main() { + call_foo::<()>() +} diff --git a/tests/ui/generic-associated-types/issue-74816.stderr b/tests/ui/generic-associated-types/issue-74816.stderr new file mode 100644 index 000000000..45018e697 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74816.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `Self: Trait1` is not satisfied + --> $DIR/issue-74816.rs:8:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ the trait `Trait1` is not implemented for `Self` + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:8:22 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Trait1 { + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-74816.rs:8:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:8:5 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Sized { + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-74824.rs b/tests/ui/generic-associated-types/issue-74824.rs new file mode 100644 index 000000000..10c45d133 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74824.rs @@ -0,0 +1,25 @@ +#![feature(associated_type_defaults)] + +use std::ops::Deref; + +trait UnsafeCopy { + type Copy<T>: Copy = Box<T>; + //~^ ERROR the trait bound `Box<T>: Copy` is not satisfied + //~^^ ERROR the trait bound `T: Clone` is not satisfied + fn copy<T>(x: &Self::Copy<T>) -> Self::Copy<T> { + *x + } +} + +impl<T> UnsafeCopy for T {} + +fn main() { + let b = Box::new(42usize); + let copy = <()>::copy(&b); + + let raw_b = Box::deref(&b) as *const _; + let raw_copy = Box::deref(©) as *const _; + + // assert the addresses. + assert_eq!(raw_b, raw_copy); +} diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr new file mode 100644 index 000000000..e5638d90e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -0,0 +1,33 @@ +error[E0277]: the trait bound `Box<T>: Copy` is not satisfied + --> $DIR/issue-74824.rs:6:26 + | +LL | type Copy<T>: Copy = Box<T>; + | ^^^^^^ the trait `Copy` is not implemented for `Box<T>` + | +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:6:19 + | +LL | type Copy<T>: Copy = Box<T>; + | ^^^^ required by this bound in `UnsafeCopy::Copy` + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/issue-74824.rs:6:26 + | +LL | type Copy<T>: Copy = Box<T>; + | ^^^^^^ the trait `Clone` is not implemented for `T` + | + = note: required for `Box<T>` to implement `Clone` + = note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy` +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:6:19 + | +LL | type Copy<T>: Copy = Box<T>; + | ^^^^ required by this bound in `UnsafeCopy::Copy` +help: consider restricting type parameter `T` + | +LL | type Copy<T: std::clone::Clone>: Copy = Box<T>; + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-76407.rs b/tests/ui/generic-associated-types/issue-76407.rs new file mode 100644 index 000000000..9556ec6da --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76407.rs @@ -0,0 +1,25 @@ +// check-pass + +trait Marker {} + +impl Marker for u32 {} + +trait MyTrait { + type Item<'a>; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + type Item<'a> = u32; +} + +fn ty_check<T>() +where + T: MyTrait, + for<'a> T::Item<'a>: Marker +{} + +fn main() { + ty_check::<MyStruct>(); +} diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr new file mode 100644 index 000000000..52c6e3eec --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -0,0 +1,52 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:39:33 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:9:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:39:14 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:9:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:39:57 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:9:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = note: required for `Box<SuperStruct>` to implement `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` + = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.extended.stderr b/tests/ui/generic-associated-types/issue-76535.extended.stderr new file mode 100644 index 000000000..369b86d29 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:39:33 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:9:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs new file mode 100644 index 000000000..2457a05a0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.rs @@ -0,0 +1,43 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait SubTrait {} + +pub trait SuperTrait { + type SubType<'a>: SubTrait where Self: 'a; + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; +} + +pub struct SubStruct<'a> { + sup: &'a mut SuperStruct, +} + +impl<'a> SubTrait for SubStruct<'a> {} + +pub struct SuperStruct { + value: u8, +} + +impl SuperStruct { + pub fn new(value: u8) -> SuperStruct { + SuperStruct { value } + } +} + +impl SuperTrait for SuperStruct { + type SubType<'a> = SubStruct<'a>; + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a> { + SubStruct { sup: self } + } +} + +fn main() { + let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + //~^ ERROR missing generics for associated type + //[base]~^^ ERROR the trait + //[base]~| ERROR the trait +} diff --git a/tests/ui/generic-associated-types/issue-76826.rs b/tests/ui/generic-associated-types/issue-76826.rs new file mode 100644 index 000000000..ead78453e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76826.rs @@ -0,0 +1,42 @@ +// run-pass + +pub trait Iter { + type Item<'a> where Self: 'a; + + fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>; + + fn for_each<F>(mut self, mut f: F) + where Self: Sized, F: for<'a> FnMut(Self::Item<'a>) + { + while let Some(item) = self.next() { + f(item); + } + } +} + +pub struct Windows<T> { + items: Vec<T>, + start: usize, + len: usize, +} + +impl<T> Windows<T> { + pub fn new(items: Vec<T>, len: usize) -> Self { + Self { items, start: 0, len } + } +} + +impl<T> Iter for Windows<T> { + type Item<'a> = &'a mut [T] where T: 'a; + + fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> { + let slice = self.items.get_mut(self.start..self.start + self.len)?; + self.start += 1; + Some(slice) + } +} + +fn main() { + Windows::new(vec![1, 2, 3, 4, 5], 3) + .for_each(|slice| println!("{:?}", slice)); +} diff --git a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs new file mode 100644 index 000000000..fd3b967d9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs @@ -0,0 +1,38 @@ +// Test for diagnostics when we have mismatched lifetime due to implicit 'static lifetime in GATs + +// check-fail + +pub trait A {} +impl A for &dyn A {} +impl A for Box<dyn A> {} + +pub trait B { + type T<'a>: A; +} + +impl B for () { + // `'a` doesn't match implicit `'static`: suggest `'_` + type T<'a> = Box<dyn A + 'a>; //~ incompatible lifetime on type +} + +trait C {} +impl C for Box<dyn A + 'static> {} +pub trait D { + type T<'a>: C; +} +impl D for () { + // `'a` doesn't match explicit `'static`: we *should* suggest removing `'static` + type T<'a> = Box<dyn A + 'a>; //~ incompatible lifetime on type +} + +trait E {} +impl E for (Box<dyn A>, Box<dyn A>) {} +pub trait F { + type T<'a>: E; +} +impl F for () { + // `'a` doesn't match explicit `'static`: suggest `'_` + type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>); //~ incompatible lifetime on type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr new file mode 100644 index 000000000..86e0f5745 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr @@ -0,0 +1,87 @@ +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:15:18 + | +LL | type T<'a> = Box<dyn A + 'a>; + | ^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:10:17 + | +LL | type T<'a>: A; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:15:12 + | +LL | type T<'a> = Box<dyn A + 'a>; + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:7:20 + | +LL | impl A for Box<dyn A> {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl A for Box<dyn A + '_> {} + | ++++ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:25:18 + | +LL | type T<'a> = Box<dyn A + 'a>; + | ^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:21:17 + | +LL | type T<'a>: C; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:25:12 + | +LL | type T<'a> = Box<dyn A + 'a>; + | ^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:19:1 + | +LL | impl C for Box<dyn A + 'static> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:35:18 + | +LL | type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:17 + | +LL | type T<'a>: E; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:35:12 + | +LL | type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>); + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:29:21 + | +LL | impl E for (Box<dyn A>, Box<dyn A>) {} + | ^ +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:29:33 + | +LL | impl E for (Box<dyn A>, Box<dyn A>) {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box<dyn A + '_>, Box<dyn A>) {} + | ++++ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box<dyn A>, Box<dyn A + '_>) {} + | ++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/issue-78671.base.stderr b/tests/ui/generic-associated-types/issue-78671.base.stderr new file mode 100644 index 000000000..bad8c1c9d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.base.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:10:47 + | +LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:7:10 + | +LL | type Member<T>; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> + | +++ + +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:10:25 + | +LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-78671.rs:7:10 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member<T>; + | ^^^^^^ ...because it contains the generic associated type `Member` + = help: consider moving `Member` to another trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-78671.extended.stderr b/tests/ui/generic-associated-types/issue-78671.extended.stderr new file mode 100644 index 000000000..1d8a3d410 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:10:47 + | +LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:7:10 + | +LL | type Member<T>; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs new file mode 100644 index 000000000..327b0c14a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.rs @@ -0,0 +1,17 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait CollectionFamily { + type Member<T>; +} +fn floatify() { + Box::new(Family) as &dyn CollectionFamily<Member=usize> + //~^ ERROR: missing generics for associated type + //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object +} + +struct Family; + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr new file mode 100644 index 000000000..f1de77bc3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -0,0 +1,52 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:47:36 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:23:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:47:12 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:23:10 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:44:13 + | +LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:23:10 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = note: required for `Box<BTreeMap<u8, u8>>` to implement `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` + = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr new file mode 100644 index 000000000..d79de0ca6 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:47:36 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:23:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:44:13 + | +LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + | +note: expected this to be `(dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:28:25 + | +LL | type VRefCont<'a> = &'a V where Self: 'a; + | ^^^^^ + = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` + found reference `&u8` + = note: required for the cast from `BTreeMap<u8, u8>` to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0271. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs new file mode 100644 index 000000000..a52dd792d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -0,0 +1,50 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait RefCont<'a, T> { + fn t(&'a self) -> &'a T; +} + +impl<'a, T> RefCont<'a, T> for &'a T { + fn t(&'a self) -> &'a T { + self + } +} + +impl<'a, T> RefCont<'a, T> for Box<T> { + fn t(&'a self) -> &'a T { + self.as_ref() + } +} + +trait MapLike<K, V> { + type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>; +} + +impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> { + type VRefCont<'a> = &'a V where Self: 'a; + fn get<'a>(&'a self, key: &K) -> Option<&'a V> { + std::collections::BTreeMap::get(self, key) + } +} + +struct Source; + +impl<K, V: Default> MapLike<K, V> for Source { + type VRefCont<'a> = Box<V>; + fn get<'a>(&self, _: &K) -> Option<Box<V>> { + Some(Box::new(V::default())) + } +} + +fn main() { + let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + //[base]~^ ERROR the trait + //[extended]~^^ type mismatch + as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + //~^ ERROR missing generics for associated type + //[base]~^^ ERROR the trait +} diff --git a/tests/ui/generic-associated-types/issue-79636-1.rs b/tests/ui/generic-associated-types/issue-79636-1.rs new file mode 100644 index 000000000..a89039b5c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-1.rs @@ -0,0 +1,21 @@ +trait Monad { + type Unwrapped; + type Wrapped<B>; + + fn bind<B, F>(self, f: F) -> Self::Wrapped<B> { + todo!() + } +} + +fn join<MOuter, MInner, A>(outer: MOuter) -> MOuter::Wrapped<A> +where + MOuter: Monad<Unwrapped = MInner>, + MInner: Monad<Unwrapped = A, Wrapped = MOuter::Wrapped<A>>, + //~^ ERROR: missing generics for associated type `Monad::Wrapped` +{ + outer.bind(|inner| inner) +} + +fn main() { + assert_eq!(join(Some(Some(true))), Some(true)); +} diff --git a/tests/ui/generic-associated-types/issue-79636-1.stderr b/tests/ui/generic-associated-types/issue-79636-1.stderr new file mode 100644 index 000000000..6e0d2ff4d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-1.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Monad::Wrapped` + --> $DIR/issue-79636-1.rs:13:34 + | +LL | MInner: Monad<Unwrapped = A, Wrapped = MOuter::Wrapped<A>>, + | ^^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `B` + --> $DIR/issue-79636-1.rs:3:10 + | +LL | type Wrapped<B>; + | ^^^^^^^ - +help: add missing generic argument + | +LL | MInner: Monad<Unwrapped = A, Wrapped<B> = MOuter::Wrapped<A>>, + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79636-2.rs b/tests/ui/generic-associated-types/issue-79636-2.rs new file mode 100644 index 000000000..ff5ff38c9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-2.rs @@ -0,0 +1,15 @@ +trait SomeTrait { + type Wrapped<A>: SomeTrait; + + fn f() -> (); +} + +fn program<W>() -> () +where + W: SomeTrait<Wrapped = W>, + //~^ ERROR: missing generics for associated type `SomeTrait::Wrapped` +{ + return W::f(); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-79636-2.stderr b/tests/ui/generic-associated-types/issue-79636-2.stderr new file mode 100644 index 000000000..162873239 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-2.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SomeTrait::Wrapped` + --> $DIR/issue-79636-2.rs:9:18 + | +LL | W: SomeTrait<Wrapped = W>, + | ^^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `A` + --> $DIR/issue-79636-2.rs:2:10 + | +LL | type Wrapped<A>: SomeTrait; + | ^^^^^^^ - +help: add missing generic argument + | +LL | W: SomeTrait<Wrapped<A> = W>, + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-80433-reduced.rs b/tests/ui/generic-associated-types/issue-80433-reduced.rs new file mode 100644 index 000000000..44831a995 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433-reduced.rs @@ -0,0 +1,21 @@ +// check-pass + +struct E {} + +trait TestMut { + type Output<'a>; + fn test_mut(&mut self) -> Self::Output<'static>; +} + +impl TestMut for E { + type Output<'a> = usize; + fn test_mut(&mut self) -> Self::Output<'static> { + todo!() + } +} + +fn test_simpler<'a>(_: impl TestMut<Output<'a> = usize>) {} + +fn main() { + test_simpler(E {}); +} diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs new file mode 100644 index 000000000..05ff82fa7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -0,0 +1,32 @@ +#[derive(Default)] +struct E<T> { + data: T, +} + +trait TestMut { + type Output<'a>; + fn test_mut<'a>(&'a mut self) -> Self::Output<'a>; +} + +impl<T> TestMut for E<T> +where + T: 'static, +{ + type Output<'a> = &'a mut T; + fn test_mut<'a>(&'a mut self) -> Self::Output<'a> { + &mut self.data + } +} + +fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>) + //~^ ERROR missing generics for associated type +{ + for n in 0i16..100 { + *dst.test_mut() = n.into(); + } +} + +fn main() { + let mut t1: E<f32> = Default::default(); + test_simpler(&mut t1); +} diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr new file mode 100644 index 000000000..4f4f96a4b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `TestMut::Output` + --> $DIR/issue-80433.rs:21:47 + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>) + | ^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-80433.rs:7:10 + | +LL | type Output<'a>; + | ^^^^^^ -- +help: add missing lifetime argument + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output<'a> = &'a mut f32>) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81487.rs b/tests/ui/generic-associated-types/issue-81487.rs new file mode 100644 index 000000000..0d19a75bb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81487.rs @@ -0,0 +1,17 @@ +// build-pass + +trait Trait { + type Ref<'a>; +} + +impl Trait for () { + type Ref<'a> = &'a i8; +} + +struct RefRef<'a, T: Trait>(&'a <T as Trait>::Ref<'a>); + +fn wrap<'a, T: Trait>(reff: &'a <T as Trait>::Ref<'a>) -> RefRef<'a, T> { + RefRef(reff) +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs new file mode 100644 index 000000000..a7cc9a605 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs @@ -0,0 +1,18 @@ +// Regression test for #81712. + +trait A { + type BType: B<AType = Self>; +} + +trait B { + type AType: A<BType = Self>; +} +trait C { + type DType<T>: D<T, CType = Self>; +} +trait D<T> { + type CType: C<DType = Self>; + //~^ ERROR missing generics for associated type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr new file mode 100644 index 000000000..e0fc225f4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `C::DType` + --> $DIR/issue-81712-cyclic-traits.rs:14:19 + | +LL | type CType: C<DType = Self>; + | ^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-81712-cyclic-traits.rs:11:10 + | +LL | type DType<T>: D<T, CType = Self>; + | ^^^^^ - +help: add missing generic argument + | +LL | type CType: C<DType<T> = Self>; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81862.rs b/tests/ui/generic-associated-types/issue-81862.rs new file mode 100644 index 000000000..bde828b77 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81862.rs @@ -0,0 +1,10 @@ +trait StreamingIterator { + type Item<'a>; + fn next(&mut self) -> Option<Self::Item>; + //~^ ERROR missing generics for associated type +} + +fn main() {} + +// call stack from back to front: +// create_substs_for_assoc_ty -> qpath_to_ty -> res_to_ty -> ast_ty_to_ty -> ty_of_fn diff --git a/tests/ui/generic-associated-types/issue-81862.stderr b/tests/ui/generic-associated-types/issue-81862.stderr new file mode 100644 index 000000000..df30be65e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81862.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `StreamingIterator::Item` + --> $DIR/issue-81862.rs:3:40 + | +LL | fn next(&mut self) -> Option<Self::Item>; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-81862.rs:2:10 + | +LL | type Item<'a>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn next(&mut self) -> Option<Self::Item<'_>>; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-84931.rs b/tests/ui/generic-associated-types/issue-84931.rs new file mode 100644 index 000000000..4123ce9d4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-84931.rs @@ -0,0 +1,21 @@ +// check-fail + +trait StreamingIter { + type Item<'a> where Self: 'a; + fn next<'a>(&'a mut self) -> Option<Self::Item::<'a>>; +} + +struct StreamingSliceIter<'a, T> { + idx: usize, + data: &'a mut [T], +} + +impl<'b, T: 'b> StreamingIter for StreamingSliceIter<'b, T> { + type Item<'a> = &'a mut T; + //~^ the parameter type + fn next(&mut self) -> Option<&mut T> { + loop {} + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-84931.stderr b/tests/ui/generic-associated-types/issue-84931.stderr new file mode 100644 index 000000000..fffea98a4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-84931.stderr @@ -0,0 +1,11 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-84931.rs:14:21 + | +LL | type Item<'a> = &'a mut T; + | ^^^^^^^^^- help: consider adding a where clause: `where T: 'a` + | | + | ...so that the reference type `&'a mut T` does not outlive the data it points at + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/generic-associated-types/issue-85921.rs b/tests/ui/generic-associated-types/issue-85921.rs new file mode 100644 index 000000000..d281ed9ee --- /dev/null +++ b/tests/ui/generic-associated-types/issue-85921.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Trait { + type Assoc<'a>; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)); +} + +impl Trait for () { + type Assoc<'a> = i32; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)) { + f(5i32) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86218-2.rs b/tests/ui/generic-associated-types/issue-86218-2.rs new file mode 100644 index 000000000..63c839ea8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86218-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay<AdditionalValue> { + type InnerStream<'s>: Stream<Item = i32> + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl<T> Yay<T> for () { + type InnerStream<'s> = impl Stream<Item = i32> + 's; + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86218.rs b/tests/ui/generic-associated-types/issue-86218.rs new file mode 100644 index 000000000..b2c3071f0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86218.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay<AdditionalValue> { + type InnerStream<'s>: Stream<Item = i32> + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl<'a> Yay<&'a ()> for () { + type InnerStream<'s> = impl Stream<Item = i32> + 's; + //^ ERROR does not fulfill the required lifetime + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86483.rs b/tests/ui/generic-associated-types/issue-86483.rs new file mode 100644 index 000000000..70267637a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86483.rs @@ -0,0 +1,14 @@ +// Regression test of #86483. +// +// Made to pass as part of fixing #98095. +// +// check-pass + +pub trait IceIce<T> +where + for<'a> T: 'a, +{ + type Ice<'v>: IntoIterator<Item = &'v T>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86787.rs b/tests/ui/generic-associated-types/issue-86787.rs new file mode 100644 index 000000000..96075ca50 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86787.rs @@ -0,0 +1,37 @@ +// check-fail + +enum Either<L, R> { + Left(L), + Right(R), +} + +pub trait HasChildrenOf { + type T; + type TRef<'a>; + //~^ missing required + + fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>; + fn take_children(self) -> Vec<Self::T>; +} + +impl<Left, Right> HasChildrenOf for Either<Left, Right> +where + Left: HasChildrenOf, + Right: HasChildrenOf, +{ + type T = Either<Left::T, Right::T>; + type TRef<'a> = Either<&'a Left::T, &'a Right::T> + where + <Left as HasChildrenOf>::T: 'a, + <Right as HasChildrenOf>::T: 'a; + + fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>> { + todo!() + } + + fn take_children(self) -> Vec<Self::T> { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86787.stderr b/tests/ui/generic-associated-types/issue-86787.stderr new file mode 100644 index 000000000..f34c63cf7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86787.stderr @@ -0,0 +1,13 @@ +error: missing required bound on `TRef` + --> $DIR/issue-86787.rs:10:5 + | +LL | type TRef<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87258_a.rs b/tests/ui/generic-associated-types/issue-87258_a.rs new file mode 100644 index 000000000..9ab683d3d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_a.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = impl Trait1; + //~^ ERROR unconstrained opaque type + fn foo<'a>() -> Self::FooFuture<'a> { + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr new file mode 100644 index 000000000..eae9bd9b1 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_a.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_a.rs:17:26 + | +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ + | + = note: `FooFuture` must be used in combination with a concrete type within the same impl + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87258_b.rs b/tests/ui/generic-associated-types/issue-87258_b.rs new file mode 100644 index 000000000..7b7610b21 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_b.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; +//~^ ERROR unconstrained opaque type + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = Helper<'c, 'a, S>; + fn foo<'a>() -> Self::FooFuture<'a> { + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr new file mode 100644 index 000000000..0ee665f38 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_b.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_b.rs:16:49 + | +LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + | ^^^^^^^^^^^ + | + = note: `Helper` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87429-2.rs b/tests/ui/generic-associated-types/issue-87429-2.rs new file mode 100644 index 000000000..feb43ee5a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-2.rs @@ -0,0 +1,18 @@ +// Derived from `issue-87429`. A test that ensures that using bound vars in the +// predicates in the param env when checking that an associated type satisfies +// its bounds does not cause us to not be able to use the bounds on the parameters. + +// check-pass + +trait Family { + type Member<'a, C: Eq>: for<'b> MyBound<'b, C>; +} + +trait MyBound<'a, C> { } +impl<'a, C: Eq> MyBound<'a, C> for i32 { } + +impl Family for () { + type Member<'a, C: Eq> = i32; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs b/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs new file mode 100644 index 000000000..2006f9bc7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs @@ -0,0 +1,17 @@ +// check-fail + +#![feature(associated_type_defaults)] + +trait Family { + // Fine, i32: PartialEq<i32> + type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = i32; +} + +struct Foo; +trait Family2 { + // Not fine, not Foo: PartialEq<Foo> + type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr new file mode 100644 index 000000000..b1abe012b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr @@ -0,0 +1,20 @@ +error[E0277]: can't compare `Foo` with `Foo` + --> $DIR/issue-87429-associated-type-default.rs:13:60 + | +LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; + | ^^^ no implementation for `Foo == Foo` + | + = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family2::Member` + --> $DIR/issue-87429-associated-type-default.rs:13:22 + | +LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.rs b/tests/ui/generic-associated-types/issue-87429-specialization.rs new file mode 100644 index 000000000..6e31f1b21 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-specialization.rs @@ -0,0 +1,24 @@ +// check-fail + +#![feature(specialization)] +//~^ WARN incomplete + +trait Family { + type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; +} + +struct I32Family; + +impl Family for I32Family { + default type Member<'a> = i32; +} + +struct Foo; +struct FooFamily; + +impl Family for FooFamily { + default type Member<'a> = Foo; + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.stderr b/tests/ui/generic-associated-types/issue-87429-specialization.stderr new file mode 100644 index 000000000..11c4ebf60 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-specialization.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-87429-specialization.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `Foo` with `Foo` + --> $DIR/issue-87429-specialization.rs:20:31 + | +LL | default type Member<'a> = Foo; + | ^^^ no implementation for `Foo == Foo` + | + = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family::Member` + --> $DIR/issue-87429-specialization.rs:7:22 + | +LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-87429.rs b/tests/ui/generic-associated-types/issue-87429.rs new file mode 100644 index 000000000..56394823c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429.rs @@ -0,0 +1,13 @@ +// check-pass + +trait Family { + type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; +} + +struct I32; + +impl Family for I32 { + type Member<'a> = i32; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87748.rs b/tests/ui/generic-associated-types/issue-87748.rs new file mode 100644 index 000000000..6cbe3d902 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87748.rs @@ -0,0 +1,21 @@ +// Checks that we properly add implied bounds from unnormalized projections in +// inputs when typechecking functions. + +// check-pass + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); + fn do_sth2(arg: Self::Assoc<'_, '_>) {} +} + +struct Foo; + +impl MyTrait for Foo { + type Assoc<'a, 'b> = u32 where 'b: 'a; + + fn do_sth(_: u32) {} + fn do_sth2(_: Self::Assoc<'static, 'static>) {} +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87750.rs b/tests/ui/generic-associated-types/issue-87750.rs new file mode 100644 index 000000000..b35657989 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87750.rs @@ -0,0 +1,24 @@ +// check-pass + +trait PointerFamily { + type Pointer<T>; +} + +struct Rc<T>(Box<T>); +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer<T> = Rc<T>; +} + +#[allow(dead_code)] +enum Node<T, P: PointerFamily> +where + P::Pointer<Node<T, P>>: Sized, +{ + Cons(P::Pointer<Node<T, P>>), +} + +fn main() { + let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>; +} diff --git a/tests/ui/generic-associated-types/issue-88287.rs b/tests/ui/generic-associated-types/issue-88287.rs new file mode 100644 index 000000000..82188493d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88287.rs @@ -0,0 +1,39 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait SearchableResource<Criteria> { + type SearchResult; +} + +trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> { + type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f + where + A: SearchableResource<B>, + Self: 'f; + + fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>; +} + +type SearchFutureTy<'f, A, B: 'f> +where + A: SearchableResource<B> + ?Sized + 'f, += impl Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f; +impl<T, Criteria> SearchableResourceExt<Criteria> for T +where + T: SearchableResource<Criteria>, +{ + type Future<'f, A, B: 'f> = SearchFutureTy<'f, A, B> + where + A: SearchableResource<B> + ?Sized + 'f, + Self: 'f; + + fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> { + async move { todo!() } + //~^ ERROR: the size for values of type `A` cannot be known at compilation time + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr new file mode 100644 index 000000000..1b84cce62 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -0,0 +1,27 @@ +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/issue-88287.rs:34:9 + | +LL | type SearchFutureTy<'f, A, B: 'f> + | - this type parameter needs to be `std::marker::Sized` +... +LL | async move { todo!() } + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `<T as SearchableResourceExt<Criteria>>` + --> $DIR/issue-88287.rs:24:6 + | +LL | impl<T, Criteria> SearchableResourceExt<Criteria> for T + | ^ required by this bound in `<T as SearchableResourceExt<Criteria>>` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - A: SearchableResource<B> + ?Sized + 'f, +LL + A: SearchableResource<B> + 'f, + | +help: consider relaxing the implicit `Sized` restriction + | +LL | T: SearchableResource<Criteria> + ?Sized, + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs new file mode 100644 index 000000000..c02690618 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -0,0 +1,18 @@ +trait GatTrait { + type Gat<'a> where Self: 'a; + + fn test(&self) -> Self::Gat<'_>; +} + +trait SuperTrait<T> +where + Self: 'static, + for<'a> Self: GatTrait<Gat<'a> = &'a T>, +{ + fn copy(&self) -> Self::Gat<'_> where T: Copy { + *self.test() + //~^ mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr new file mode 100644 index 000000000..cd3750344 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-88360.rs:13:9 + | +LL | trait SuperTrait<T> + | - this type parameter +... +LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { + | ------------- expected `&T` because of return type +LL | *self.test() + | ^^^^^^^^^^^^ + | | + | expected `&T`, found type parameter `T` + | help: consider borrowing here: `&*self.test()` + | + = note: expected reference `&T` + found type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-88405.rs b/tests/ui/generic-associated-types/issue-88405.rs new file mode 100644 index 000000000..8dad6a89f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88405.rs @@ -0,0 +1,14 @@ +// check-pass + +trait SomeTrait {} +trait OtherTrait { + type Item; +} + +trait ErrorSimpleExample { + type AssociatedType: SomeTrait; + type GatBounded<T: SomeTrait>; + type ErrorMinimal: OtherTrait<Item = Self::GatBounded<Self::AssociatedType>>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88459.rs b/tests/ui/generic-associated-types/issue-88459.rs new file mode 100644 index 000000000..07d7bc06d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88459.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Trait { + type Assoc<'a>; +} + +fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {} + +struct Type; + +impl Trait for Type { + type Assoc<'a> = (); +} + +fn main() { + f(Type, |_|()); +} diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs new file mode 100644 index 000000000..24641ee1f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88595.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait A<'a> { + type B<'b>: Clone + // FIXME(generic_associated_types): Remove one of the below bounds + // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085 + where + Self: 'a, Self: 'b; + + fn a(&'a self) -> Self::B<'a>; +} + +struct C; + +impl<'a> A<'a> for C { + type B<'b> = impl Clone; + + fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope +} diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr new file mode 100644 index 000000000..bcefc8066 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -0,0 +1,16 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-88595.rs:20:35 + | +LL | fn a(&'a self) -> Self::B<'a> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/issue-88595.rs:17:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +LL | type B<'b> = impl Clone; + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-89008.rs b/tests/ui/generic-associated-types/issue-89008.rs new file mode 100644 index 000000000..669dbafb5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-89008.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2021 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; +use std::marker::PhantomData; + +trait Stream { + type Item; +} + +struct Empty<T> { + _phantom: PhantomData<T>, +} + +impl<T> Stream for Empty<T> { + type Item = T; +} + +trait X { + type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a; + type LineStreamFut<'a, Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a; + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr>; +} + +struct Y; + +impl X for Y { + type LineStream<'a, Repr> = impl Stream<Item = Repr>; + type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>; + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { + async { Empty { _phantom: PhantomData } } + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-89352.rs b/tests/ui/generic-associated-types/issue-89352.rs new file mode 100644 index 000000000..1896d0c87 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-89352.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait GenAssoc<T> { + type Iter<'at>; + fn iter(&self) -> Self::Iter<'_>; + fn reborrow<'longt: 'shortt, 'shortt>(iter: Self::Iter<'longt>) -> Self::Iter<'shortt>; +} + +pub struct Wrapper<'a, T: 'a, A: GenAssoc<T>> { + a: A::Iter<'a>, + _p: PhantomData<T>, +} + +impl<'ai, T: 'ai, A: GenAssoc<T>> GenAssoc<T> for Wrapper<'ai, T, A> +where + A::Iter<'ai>: Clone, +{ + type Iter<'b> = (); + fn iter<'s>(&'s self) -> Self::Iter<'s> { + let a = A::reborrow::<'ai, 's>(self.a.clone()); + } + + fn reborrow<'long: 'short, 'short>(iter: Self::Iter<'long>) -> Self::Iter<'short> { + () + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014.rs b/tests/ui/generic-associated-types/issue-90014.rs new file mode 100644 index 000000000..55db95a6d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014.rs @@ -0,0 +1,21 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait MakeFut { + type Fut<'a> where Self: 'a; + fn make_fut<'a>(&'a self) -> Self::Fut<'a>; +} + +impl MakeFut for &'_ mut () { + type Fut<'a> = impl Future<Output = ()>; + //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime + + fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + async { () } + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014.stderr b/tests/ui/generic-associated-types/issue-90014.stderr new file mode 100644 index 000000000..b4b1bc7da --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014.stderr @@ -0,0 +1,22 @@ +error[E0477]: the type `&mut ()` does not fulfill the required lifetime + --> $DIR/issue-90014.rs:13:20 + | +LL | type Fut<'a> where Self: 'a; + | ------------ definition of `Fut` from trait +... +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-90014.rs:13:14 + | +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type Fut<'a> = impl Future<Output = ()> where Self: 'a; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-90729.rs b/tests/ui/generic-associated-types/issue-90729.rs new file mode 100644 index 000000000..bcec2e321 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90729.rs @@ -0,0 +1,36 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait Type { + type Ref<'a>; +} + +pub trait AsBytes {} + +impl AsBytes for &str {} + +pub struct Utf8; + +impl Type for Utf8 { + type Ref<'a> = &'a str; +} + +pub struct Bytes<T: Type> { + _marker: PhantomData<T>, +} + +impl<T: Type> Bytes<T> +where + for<'a> T::Ref<'a>: AsBytes, +{ + pub fn new() -> Self { + Self { + _marker: PhantomData, + } + } +} + +fn main() { + let _b = Bytes::<Utf8>::new(); +} diff --git a/tests/ui/generic-associated-types/issue-91139.migrate.stderr b/tests/ui/generic-associated-types/issue-91139.migrate.stderr new file mode 100644 index 000000000..690160577 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.migrate.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `<<` + --> $DIR/issue-91139.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-91139.rs b/tests/ui/generic-associated-types/issue-91139.rs new file mode 100644 index 000000000..adc0cb4e0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.rs @@ -0,0 +1,27 @@ +trait Foo<T> { + type Type<'a> + where + T: 'a; +} + +impl<T> Foo<T> for () { + type Type<'a> = () + where + T: 'a; +} + +fn foo<T>() { + let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + //~^ ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + // + // FIXME: This error is bogus, but it arises because we try to validate + // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving + // that `T: 'a`. Since `'a` is higher-ranked, this becomes + // `for<'a> T: 'a`, which is not true. Of course, the error is bogus + // because there *ought* to be an implied bound stating that `'a` is + // not any lifetime but specifically + // "some `'a` such that `<() as Foo<T>>::Type<'a>" is valid". +} + +pub fn main() {} diff --git a/tests/ui/generic-associated-types/issue-91139.stderr b/tests/ui/generic-associated-types/issue-91139.stderr new file mode 100644 index 000000000..d9d76adfb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.stderr @@ -0,0 +1,14 @@ +error: `T` does not live long enough + --> $DIR/issue-91139.rs:14:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:14:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/issue-91883.rs b/tests/ui/generic-associated-types/issue-91883.rs new file mode 100644 index 000000000..e870e08a3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91883.rs @@ -0,0 +1,40 @@ +use std::fmt::Debug; +use std::marker::PhantomData; + +#[derive(Debug)] +pub struct TransactionImpl<'db> { + _marker: PhantomData<&'db ()>, +} + +#[derive(Debug)] +pub struct CursorImpl<'txn> { + _marker: PhantomData<&'txn ()>, +} + +pub trait Cursor<'txn> {} + +pub trait Transaction<'db>: Send + Sync + Debug + Sized { + type Cursor<'tx>: Cursor<'tx> + where + 'db: 'tx, + Self: 'tx; + + fn cursor<'tx>(&'tx self) -> Result<Self::Cursor<'tx>, ()> + where + 'db: 'tx; +} + +impl<'tx> Cursor<'tx> for CursorImpl<'tx> {} + +impl<'db> Transaction<'db> for TransactionImpl<'db> { + type Cursor<'tx> = CursorImpl<'tx>; //~ ERROR lifetime bound not satisfied + + fn cursor<'tx>(&'tx self) -> Result<Self::Cursor<'tx>, ()> + where + 'db: 'tx, + { + loop {} + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.stderr new file mode 100644 index 000000000..d5db96209 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91883.stderr @@ -0,0 +1,27 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-91883.rs:30:24 + | +LL | type Cursor<'tx>: Cursor<'tx> + | ----------------------------- definition of `Cursor` from trait +... +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'db` as defined here + --> $DIR/issue-91883.rs:29:6 + | +LL | impl<'db> Transaction<'db> for TransactionImpl<'db> { + | ^^^ +note: but lifetime parameter must outlive the lifetime `'tx` as defined here + --> $DIR/issue-91883.rs:30:17 + | +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^ +help: copy the `where` clause predicates from the trait + | +LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; + | +++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/generic-associated-types/issue-92033.rs b/tests/ui/generic-associated-types/issue-92033.rs new file mode 100644 index 000000000..d111580b8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92033.rs @@ -0,0 +1,37 @@ +struct Texture; + +trait Surface { + type TextureIter<'a>: Iterator<Item = &'a Texture> + where + Self: 'a; + + fn get_texture(&self) -> Self::TextureIter<'_>; +} + +trait Swapchain { + type Surface<'a>: Surface + where + Self: 'a; + + fn get_surface(&self) -> Self::Surface<'_>; +} + +impl<'s> Surface for &'s Texture { + type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + //~^ ERROR the type + + fn get_texture(&self) -> Self::TextureIter<'_> { + let option: Option<&Texture> = Some(self); + option.into_iter() + } +} + +impl Swapchain for Texture { + type Surface<'a> = &'a Texture; + + fn get_surface(&self) -> Self::Surface<'_> { + self + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92033.stderr b/tests/ui/generic-associated-types/issue-92033.stderr new file mode 100644 index 000000000..ddc420a7b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92033.stderr @@ -0,0 +1,22 @@ +error[E0477]: the type `&'s Texture` does not fulfill the required lifetime + --> $DIR/issue-92033.rs:20:28 + | +LL | type TextureIter<'a>: Iterator<Item = &'a Texture> + | -------------------------------------------------- definition of `TextureIter` from trait +... +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-92033.rs:20:22 + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-92096.migrate.stderr b/tests/ui/generic-associated-types/issue-92096.migrate.stderr new file mode 100644 index 000000000..ce1fd6dd9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.migrate.stderr @@ -0,0 +1,24 @@ +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:19:33 + | +LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send + | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | C: Client + Send + Sync + 'a, + | ++++ + +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:19:33 + | +LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send + | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | C: Client + Send + Sync + 'a, + | ++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/issue-92096.rs b/tests/ui/generic-associated-types/issue-92096.rs new file mode 100644 index 000000000..e285af666 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.rs @@ -0,0 +1,28 @@ +// edition:2018 + +use std::future::Future; + +trait Client { + type Connecting<'a>: Future + Send + where + Self: 'a; + + fn connect(&'_ self) -> Self::Connecting<'_>; +} + +fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send +where + C: Client + Send + Sync, +{ + async move { c.connect().await } + //~^ ERROR `C` does not live long enough + // + // FIXME(#71723). This is because we infer at some point a value of + // + // impl Future<Output = <C as Client>::Connection<'_>> + // + // and then we somehow fail the WF check because `where C: 'a` is not known, + // but I'm not entirely sure how that comes about. +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92096.stderr b/tests/ui/generic-associated-types/issue-92096.stderr new file mode 100644 index 000000000..91a06d5ac --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.stderr @@ -0,0 +1,8 @@ +error: `C` does not live long enough + --> $DIR/issue-92096.rs:17:5 + | +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-92280.rs b/tests/ui/generic-associated-types/issue-92280.rs new file mode 100644 index 000000000..9284beea3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92280.rs @@ -0,0 +1,24 @@ +// check-pass + +#![allow(non_camel_case_types)] + +trait HasAssoc { + type Assoc; +} + +trait Iterate<S: HasAssoc> { + type Iter<'a> + where + Self: 'a; +} + +struct KeySegment_Broken<T> { + key: T, +} +impl<S: HasAssoc> Iterate<S> for KeySegment_Broken<S::Assoc> { + type Iter<'a> = () + where + Self: 'a; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92954.rs b/tests/ui/generic-associated-types/issue-92954.rs new file mode 100644 index 000000000..22ce8f9fe --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92954.rs @@ -0,0 +1,8 @@ +// check-pass + +pub trait Foo { + type Assoc<'c>; + fn function() -> for<'x> fn(Self::Assoc<'x>); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93141.rs b/tests/ui/generic-associated-types/issue-93141.rs new file mode 100644 index 000000000..48c78b9c0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93141.rs @@ -0,0 +1,23 @@ +// check-pass + +pub trait Fooey: Sized { + type Context<'c> where Self: 'c; +} + +pub struct Handle<E: Fooey>(Option<Box<dyn for<'c> Fn(&mut E::Context<'c>)>>); + +fn tuple<T>() -> (Option<T>,) { (Option::None,) } + +pub struct FooImpl {} +impl Fooey for FooImpl { + type Context<'c> = &'c (); +} + +impl FooImpl { + pub fn fail1() -> Handle<Self> { + let (tx,) = tuple(); + Handle(tx) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93262.rs b/tests/ui/generic-associated-types/issue-93262.rs new file mode 100644 index 000000000..a7bcd111d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93262.rs @@ -0,0 +1,19 @@ +// check-pass + +pub trait Trait { + type Assoc<'a> where Self: 'a; +} + +pub trait Foo<T: Trait> +where + for<'a> T::Assoc<'a>: Clone +{} + +pub struct Type; + +impl<T: Trait> Foo<T> for Type +where + for<'a> T::Assoc<'a>: Clone +{} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93340.rs b/tests/ui/generic-associated-types/issue-93340.rs new file mode 100644 index 000000000..4662fda53 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93340.rs @@ -0,0 +1,18 @@ +// check-pass + +pub trait Scalar: 'static { + type RefType<'a>: ScalarRef<'a>; +} + +pub trait ScalarRef<'a>: 'a {} + +fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O { + todo!() +} + +fn build_expression<A: Scalar, B: Scalar, O: Scalar>( +) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + cmp_eq +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93341.rs b/tests/ui/generic-associated-types/issue-93341.rs new file mode 100644 index 000000000..737b2bbdb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93341.rs @@ -0,0 +1,54 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct Id<'id>(PhantomData<fn(&'id ()) -> &'id ()>); + +fn new_id() -> Id<'static> { + Id(PhantomData) +} + +pub trait HasLifetime where { + type AtLifetime<'a>; +} + +pub struct ExistentialLifetime<S: HasLifetime>(S::AtLifetime<'static>); + +impl<S: HasLifetime> ExistentialLifetime<S> { + pub fn new<F>(f: F) -> ExistentialLifetime<S> + where for<'id> F: FnOnce(Id<'id>) -> S::AtLifetime<'id> { + ExistentialLifetime(f(new_id())) + } +} + + +struct ExampleS<'id>(Id<'id>); + +struct ExampleMarker; + +impl HasLifetime for ExampleMarker { + type AtLifetime<'id> = ExampleS<'id>; +} + + +fn broken0() -> ExistentialLifetime<ExampleMarker> { + fn new_helper<'id>(id: Id<'id>) -> ExampleS<'id> { + ExampleS(id) + } + + ExistentialLifetime::<ExampleMarker>::new(new_helper) +} + +fn broken1() -> ExistentialLifetime<ExampleMarker> { + fn new_helper<'id>(id: Id<'id>) -> <ExampleMarker as HasLifetime>::AtLifetime<'id> { + ExampleS(id) + } + + ExistentialLifetime::<ExampleMarker>::new(new_helper) +} + +fn broken2() -> ExistentialLifetime<ExampleMarker> { + ExistentialLifetime::<ExampleMarker>::new(|id| ExampleS(id)) +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93342.rs b/tests/ui/generic-associated-types/issue-93342.rs new file mode 100644 index 000000000..d4422d5d1 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93342.rs @@ -0,0 +1,55 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait Scalar: 'static { + type RefType<'a>: ScalarRef<'a>; +} + +pub trait ScalarRef<'a>: 'a {} + +impl Scalar for i32 { + type RefType<'a> = i32; +} + +impl Scalar for String { + type RefType<'a> = &'a str; +} + +impl Scalar for bool { + type RefType<'a> = i32; +} + +impl<'a> ScalarRef<'a> for bool {} + +impl<'a> ScalarRef<'a> for i32 {} + +impl<'a> ScalarRef<'a> for &'a str {} + +fn str_contains(a: &str, b: &str) -> bool { + a.contains(b) +} + +pub struct BinaryExpression<A: Scalar, B: Scalar, O: Scalar, F> +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + f: F, + _phantom: PhantomData<(A, B, O)>, +} + +impl<A: Scalar, B: Scalar, O: Scalar, F> BinaryExpression<A, B, O, F> +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + pub fn new(f: F) -> Self { + Self { + f, + _phantom: PhantomData, + } + } +} + +fn main() { + BinaryExpression::<String, String, bool, _>::new(str_contains); +} diff --git a/tests/ui/generic-associated-types/issue-93874.rs b/tests/ui/generic-associated-types/issue-93874.rs new file mode 100644 index 000000000..30956655a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93874.rs @@ -0,0 +1,33 @@ +// check-pass + +pub trait Build { + type Output<O>; + fn build<O>(self, input: O) -> Self::Output<O>; +} + +pub struct IdentityBuild; +impl Build for IdentityBuild { + type Output<O> = O; + fn build<O>(self, input: O) -> Self::Output<O> { + input + } +} + +fn a() { + let _x: u8 = IdentityBuild.build(10); +} + +fn b() { + let _x: Vec<u8> = IdentityBuild.build(Vec::new()); +} + +fn c() { + let mut f = IdentityBuild.build(|| ()); + (f)(); +} + +pub fn main() { + a(); + b(); + c(); +} diff --git a/tests/ui/generic-associated-types/issue-95305.rs b/tests/ui/generic-associated-types/issue-95305.rs new file mode 100644 index 000000000..6c3ec20e7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-95305.rs @@ -0,0 +1,19 @@ +// It's not yet clear how '_ and GATs should interact. +// Forbid it for now but proper support might be added +// at some point in the future. + +#![feature(anonymous_lifetime_in_impl_trait)] +trait Foo { + type Item<'a>; +} + +fn foo(x: &impl Foo<Item<'_> = u32>) { } + //~^ ERROR `'_` cannot be used here [E0637] + +// Ok: the anonymous lifetime is bound to the function. +fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { } + +// Ok: the anonymous lifetime is bound to the function. +fn baz(x: &impl for<'a> Foo<Item<'a> = &u32>) { } + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-95305.stderr b/tests/ui/generic-associated-types/issue-95305.stderr new file mode 100644 index 000000000..eb15cbc62 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-95305.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-95305.rs:10:26 + | +LL | fn foo(x: &impl Foo<Item<'_> = u32>) { } + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/generic-associated-types/iterable.rs b/tests/ui/generic-associated-types/iterable.rs new file mode 100644 index 000000000..8ad351bd3 --- /dev/null +++ b/tests/ui/generic-associated-types/iterable.rs @@ -0,0 +1,44 @@ +// run-pass + +trait Iterable { + type Item<'a> where Self: 'a; + type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a>; +} + +// Impl for struct type +impl<T> Iterable for Vec<T> { + type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a> { + self[..].iter() + } +} + +// Impl for a primitive type +impl<T> Iterable for [T] { + type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a> { + self.iter() + } +} + +fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> { + it.iter() +} + +fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> { + it.iter().next() +} + +fn main() { + let v = vec![1, 2, 3]; + assert_eq!(v, make_iter(&v).copied().collect::<Vec<_>>()); + assert_eq!(v, make_iter(&*v).copied().collect::<Vec<_>>()); + assert_eq!(Some(&1), get_first(&v)); + assert_eq!(Some(&1), get_first(&*v)); +} diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs new file mode 100644 index 000000000..83655341d --- /dev/null +++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -0,0 +1,33 @@ +// Test that the predicate printed in an unresolved method error prints the +// generics for a generic associated type. + +trait X { + type Y<T>; +} + +trait M { + fn f(&self) {} +} + +impl<T: X<Y<i32> = i32>> M for T {} +//~^ NOTE trait bound `<S as X>::Y<i32> = i32` was not satisfied +//~| NOTE +//~| NOTE +//~| NOTE + +struct S; +//~^ NOTE method `f` not found for this +//~| NOTE doesn't satisfy `<S as X>::Y<i32> = i32` +//~| NOTE doesn't satisfy `S: M` + +impl X for S { + type Y<T> = bool; +} + +fn f(a: S) { + a.f(); + //~^ ERROR the method `f` exists for struct `S`, but its trait bounds were not satisfied + //~| NOTE method cannot be called on `S` due to unsatisfied trait bounds +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr new file mode 100644 index 000000000..baef38f6b --- /dev/null +++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -0,0 +1,24 @@ +error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied + --> $DIR/method-unsatified-assoc-type-predicate.rs:28:7 + | +LL | struct S; + | -------- + | | + | method `f` not found for this struct + | doesn't satisfy `<S as X>::Y<i32> = i32` + | doesn't satisfy `S: M` +... +LL | a.f(); + | ^ method cannot be called on `S` due to unsatisfied trait bounds + | +note: trait bound `<S as X>::Y<i32> = i32` was not satisfied + --> $DIR/method-unsatified-assoc-type-predicate.rs:12:11 + | +LL | impl<T: X<Y<i32> = i32>> M for T {} + | ^^^^^^^^^^^^ - - + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs b/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs new file mode 100644 index 000000000..8caf53176 --- /dev/null +++ b/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs @@ -0,0 +1,12 @@ +trait Foo { + type T<'a1, 'b1> + where + 'a1: 'b1; +} + +impl Foo for () { + type T<'a2, 'b2> = () where 'b2: 'a2; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr new file mode 100644 index 000000000..91a030076 --- /dev/null +++ b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/mismatched-where-clause-regions.rs:8:38 + | +LL | type T<'a1, 'b1> + | ---------------- definition of `T` from trait +... +LL | type T<'a2, 'b2> = () where 'b2: 'a2; + | ^^^ impl has extra requirement `'b2: 'a2` + | +help: copy the `where` clause predicates from the trait + | +LL | type T<'a2, 'b2> = () where 'a2: 'b2; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed new file mode 100644 index 000000000..ee758f19e --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -0,0 +1,46 @@ +// run-rustfix + +use std::ops::Add; + +struct A<B>(B); + +impl<B> Add for A<B> where B: Add + Add<Output = B> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + A(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct C<B>(B); + +impl<B: Add + Add<Output = B>> Add for C<B> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct D<B>(B); + +impl<B: std::ops::Add<Output = B>> Add for D<B> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B` + } +} + +struct E<B>(B); + +impl<B: Add + Add<Output = B>> Add for E<B> where B: Add<Output = B> { + //~^ ERROR equality constraints are not yet supported in `where` clauses + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs new file mode 100644 index 000000000..ffafff5e9 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -0,0 +1,46 @@ +// run-rustfix + +use std::ops::Add; + +struct A<B>(B); + +impl<B> Add for A<B> where B: Add { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + A(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct C<B>(B); + +impl<B: Add> Add for C<B> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct D<B>(B); + +impl<B> Add for D<B> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B` + } +} + +struct E<B>(B); + +impl<B: Add> Add for E<B> where <B as Add>::Output = B { + //~^ ERROR equality constraints are not yet supported in `where` clauses + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr new file mode 100644 index 000000000..9f669b9a5 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -0,0 +1,105 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/missing-bounds.rs:37:33 + | +LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B { + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information +help: if `Output` is an associated type you're trying to set, use the associated type binding syntax + | +LL | impl<B: Add> Add for E<B> where B: Add<Output = B> { + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:11:11 + | +LL | impl<B> Add for A<B> where B: Add { + | - this type parameter +... +LL | A(self.0 + rhs.0) + | - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this struct are incorrect + | + = note: expected type parameter `B` + found associated type `<B as Add>::Output` +help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed + --> $DIR/missing-bounds.rs:11:9 + | +LL | A(self.0 + rhs.0) + | ^^--------------^ + | | + | this argument influences the type of `A` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:5:8 + | +LL | struct A<B>(B); + | ^ +help: consider further restricting this bound + | +LL | impl<B> Add for A<B> where B: Add + Add<Output = B> { + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:21:14 + | +LL | impl<B: Add> Add for C<B> { + | - this type parameter +... +LL | Self(self.0 + rhs.0) + | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type parameter `B` + found associated type `<B as Add>::Output` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:15:8 + | +LL | struct C<B>(B); + | ^ +help: consider further restricting this bound + | +LL | impl<B: Add + Add<Output = B>> Add for C<B> { + | +++++++++++++++++ + +error[E0369]: cannot add `B` to `B` + --> $DIR/missing-bounds.rs:31:21 + | +LL | Self(self.0 + rhs.0) + | ------ ^ ----- B + | | + | B + | +help: consider restricting type parameter `B` + | +LL | impl<B: std::ops::Add<Output = B>> Add for D<B> { + | +++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:42:14 + | +LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B { + | - this type parameter +... +LL | Self(self.0 + rhs.0) + | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type parameter `B` + found associated type `<B as Add>::Output` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:35:8 + | +LL | struct E<B>(B); + | ^ +help: consider further restricting this bound + | +LL | impl<B: Add + Add<Output = B>> Add for E<B> where <B as Add>::Output = B { + | +++++++++++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs new file mode 100644 index 000000000..de9cad308 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -0,0 +1,11 @@ +// check-fail + +trait Foo { + type Assoc<'a, 'b>; +} +impl Foo for () { + type Assoc<'a, 'b> = () where 'a: 'b; + //~^ impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr new file mode 100644 index 000000000..8a71fc73a --- /dev/null +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -0,0 +1,18 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/missing-where-clause-on-trait.rs:7:39 + | +LL | type Assoc<'a, 'b>; + | ------------------ definition of `Assoc` from trait +... +LL | type Assoc<'a, 'b> = () where 'a: 'b; + | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - type Assoc<'a, 'b> = () where 'a: 'b; +LL + type Assoc<'a, 'b> = () ; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.rs b/tests/ui/generic-associated-types/missing_lifetime_args.rs new file mode 100644 index 000000000..78def8092 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_args.rs @@ -0,0 +1,20 @@ +trait X { + type Y<'a, 'b>; +} + +struct Foo<'a, 'b, 'c> { + a: &'a u32, + b: &'b str, + c: &'c str, +} + +fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {} +//~^ ERROR missing generics for associated type + +fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} +//~^ ERROR this struct takes 3 lifetime arguments but 2 lifetime + +fn f<'a>(_arg: Foo<'a>) {} +//~^ ERROR this struct takes 3 lifetime arguments but 1 lifetime + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr new file mode 100644 index 000000000..8f74b12c0 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr @@ -0,0 +1,55 @@ +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/missing_lifetime_args.rs:11:32 + | +LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {} + | ^ expected 2 lifetime arguments + | +note: associated type defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/missing_lifetime_args.rs:2:10 + | +LL | type Y<'a, 'b>; + | ^ -- -- +help: add missing lifetime arguments + | +LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {} + | ++++++++ + +error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/missing_lifetime_args.rs:14:26 + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} + | ^^^ -- -- supplied 2 lifetime arguments + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime argument + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {} + | ++++ + +error[E0107]: this struct takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing_lifetime_args.rs:17:16 + | +LL | fn f<'a>(_arg: Foo<'a>) {} + | ^^^ -- supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime arguments + | +LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {} + | ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.rs b/tests/ui/generic-associated-types/missing_lifetime_const.rs new file mode 100644 index 000000000..8b174b9e9 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_const.rs @@ -0,0 +1,10 @@ +trait Foo { + type Assoc<'a, const N: usize>; +} + +fn foo<T: Foo>() { + let _: <T as Foo>::Assoc<3>; + //~^ ERROR this associated type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.stderr b/tests/ui/generic-associated-types/missing_lifetime_const.stderr new file mode 100644 index 000000000..62d2e9f49 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_const.stderr @@ -0,0 +1,19 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/missing_lifetime_const.rs:6:24 + | +LL | let _: <T as Foo>::Assoc<3>; + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/missing_lifetime_const.rs:2:10 + | +LL | type Assoc<'a, const N: usize>; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | let _: <T as Foo>::Assoc<'a, 3>; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/own-bound-span.rs b/tests/ui/generic-associated-types/own-bound-span.rs new file mode 100644 index 000000000..3699f7296 --- /dev/null +++ b/tests/ui/generic-associated-types/own-bound-span.rs @@ -0,0 +1,17 @@ +struct S; + +trait D { + type P<T: Copy>; + //~^ NOTE required by this bound in `D::P` + //~| NOTE required by a bound in `D::P` +} + +impl D for S { + type P<T: Copy> = (); +} + +fn main() { + let _: <S as D>::P<String>; + //~^ ERROR the trait bound `String: Copy` is not satisfied + //~| NOTE the trait `Copy` is not implemented for `String` +} diff --git a/tests/ui/generic-associated-types/own-bound-span.stderr b/tests/ui/generic-associated-types/own-bound-span.stderr new file mode 100644 index 000000000..8ab8ea623 --- /dev/null +++ b/tests/ui/generic-associated-types/own-bound-span.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/own-bound-span.rs:14:12 + | +LL | let _: <S as D>::P<String>; + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `D::P` + --> $DIR/own-bound-span.rs:4:15 + | +LL | type P<T: Copy>; + | ^^^^ required by this bound in `D::P` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.rs b/tests/ui/generic-associated-types/parameter_number_and_kind.rs new file mode 100644 index 000000000..8428e7763 --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind.rs @@ -0,0 +1,18 @@ +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a>; + type B<'a, 'b>; + type C; + type D<T>; + type E<'a, T>; + // Test parameters in default values + type FOk<T> = Self::E<'static, T>; + type FErr1 = Self::E<'static, 'static>; + //~^ ERROR this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this associated type takes 1 + type FErr2<T> = Self::E<'static, T, u32>; + //~^ ERROR this associated type takes 1 +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr new file mode 100644 index 000000000..c20b9669e --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr @@ -0,0 +1,47 @@ +error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/parameter_number_and_kind.rs:11:24 + | +LL | type FErr1 = Self::E<'static, 'static>; + | ^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ -- + +error[E0107]: this associated type takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/parameter_number_and_kind.rs:11:24 + | +LL | type FErr1 = Self::E<'static, 'static>; + | ^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ - +help: add missing generic argument + | +LL | type FErr1 = Self::E<'static, 'static, T>; + | +++ + +error[E0107]: this associated type takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/parameter_number_and_kind.rs:14:27 + | +LL | type FErr2<T> = Self::E<'static, T, u32>; + | ^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ - + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs new file mode 100644 index 000000000..c1381025a --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -0,0 +1,33 @@ +#![feature(associated_type_defaults)] + +// FIXME(#44265) add tests for type-generic and const-genertic associated types. + +trait Foo { + type A<'a>; + type B<'a, 'b>; + type C; +} + +struct Fooy; + +impl Foo for Fooy { + type A = u32; + //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration + type B<'a, T> = Vec<T>; + //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters + type C<'a> = u32; + //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration +} + +struct Fooer; + +impl Foo for Fooer { + type A<T> = u32; + //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters + type B<'a> = u32; + //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration + type C<T> = T; + //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr new file mode 100644 index 000000000..fdd6d305a --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr @@ -0,0 +1,62 @@ +error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:14:11 + | +LL | type A<'a>; + | ---- lifetimes in impl do not match this type in trait +... +LL | type A = u32; + | ^ lifetimes do not match type in trait + +error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:16:12 + | +LL | type B<'a, 'b>; + | -- -- + | | + | expected 0 type parameters +... +LL | type B<'a, T> = Vec<T>; + | ^^ ^ + | | + | found 1 type parameter + +error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:18:11 + | +LL | type C; + | - lifetimes in impl do not match this type in trait +... +LL | type C<'a> = u32; + | ^^^^ lifetimes do not match type in trait + +error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:25:12 + | +LL | type A<'a>; + | -- expected 0 type parameters +... +LL | type A<T> = u32; + | ^ found 1 type parameter + +error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:27:11 + | +LL | type B<'a, 'b>; + | -------- lifetimes in impl do not match this type in trait +... +LL | type B<'a> = u32; + | ^^^^ lifetimes do not match type in trait + +error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:29:12 + | +LL | type C; + | - expected 0 type parameters +... +LL | type C<T> = T; + | ^ found 1 type parameter + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0049, E0195. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/parse/in-trait-impl.rs b/tests/ui/generic-associated-types/parse/in-trait-impl.rs new file mode 100644 index 000000000..767098835 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/in-trait-impl.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: -Z parse-only + +impl<T> Baz for T where T: Foo { + type Quux<'a> = <T as Foo>::Bar<'a, 'static>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/in-trait.rs b/tests/ui/generic-associated-types/parse/in-trait.rs new file mode 100644 index 000000000..6628aac37 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/in-trait.rs @@ -0,0 +1,22 @@ +// check-pass +// compile-flags: -Z parse-only + +use std::ops::Deref; +use std::fmt::Debug; + +trait Foo { + type Bar<'a>; + type Bar<'a, 'b>; + type Bar<'a, 'b,>; + type Bar<'a, 'b, T>; + type Bar<'a, 'b, T, U>; + type Bar<'a, 'b, T, U,>; + type Bar<'a, 'b, T: Debug, U,>; + type Bar<'a, 'b, T: Debug, U,>: Debug; + type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U>; + type Bar<'a, 'b, T: Debug, U,> where T: Deref<Target = U>, U: Into<T>; + type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U> + where T: Deref<Target = U>, U: Into<T>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs new file mode 100644 index 000000000..cbb051892 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs @@ -0,0 +1,8 @@ +trait X { + type Y<'a>; +} + +fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {} + //~^ ERROR: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr new file mode 100644 index 000000000..53d5f9de6 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` + --> $DIR/trait-path-expected-token.rs:5:33 + | +LL | fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {} + | - ^ expected one of 7 possible tokens + | | + | maybe try to close unmatched angle bracket + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.rs b/tests/ui/generic-associated-types/parse/trait-path-expressions.rs new file mode 100644 index 000000000..9183ec497 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.rs @@ -0,0 +1,20 @@ +mod error1 { + trait X { + type Y<'a>; + } + + fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {} + //~^ ERROR: expected expression, found `)` +} + +mod error2 { + + trait X { + type Y<'a>; + } + + fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {} + //~^ ERROR: expected one of +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr new file mode 100644 index 000000000..cf2b1763f --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -0,0 +1,23 @@ +error: expected expression, found `)` + --> $DIR/trait-path-expressions.rs:6:39 + | +LL | fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {} + | - ^ expected expression + | | + | while parsing a const generic argument starting here + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-expressions.rs:16:36 + | +LL | fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f2<'a>(arg : Box<dyn X< { 1 }> = 32 >>) {} + | + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs new file mode 100644 index 000000000..ecabf8943 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -0,0 +1,18 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f1<'a>(arg : Box<dyn X< : 32 >>) {} + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `:` + //~| ERROR: expected parameter name, found `>` + //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` + //~| ERROR: constant provided when a type was expected +}; + +const _: () = { + fn f1<'a>(arg : Box<dyn X< = 32 >>) {} + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `=` +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr new file mode 100644 index 000000000..10ceccedc --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -0,0 +1,43 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `:` + --> $DIR/trait-path-missing-gen_arg.rs:6:30 + | +LL | fn f1<'a>(arg : Box<dyn X< : 32 >>) {} + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | fn f1<'a>(arg : Box<{ dyn X< : 32 } >>) {} + | + + + +error: expected parameter name, found `>` + --> $DIR/trait-path-missing-gen_arg.rs:6:36 + | +LL | fn f1<'a>(arg : Box<dyn X< : 32 >>) {} + | ^ expected parameter name + +error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` + --> $DIR/trait-path-missing-gen_arg.rs:6:36 + | +LL | fn f1<'a>(arg : Box<dyn X< : 32 >>) {} + | ^ + | | + | expected one of `!`, `)`, `+`, `,`, or `::` + | help: missing `,` + +error: expected one of `>`, a const expression, lifetime, or type, found `=` + --> $DIR/trait-path-missing-gen_arg.rs:14:30 + | +LL | fn f1<'a>(arg : Box<dyn X< = 32 >>) {} + | - ^ expected one of `>`, a const expression, lifetime, or type + | | + | maybe try to close unmatched angle bracket + +error[E0747]: constant provided when a type was expected + --> $DIR/trait-path-missing-gen_arg.rs:6:23 + | +LL | fn f1<'a>(arg : Box<dyn X< : 32 >>) {} + | ^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.rs b/tests/ui/generic-associated-types/parse/trait-path-segments.rs new file mode 100644 index 000000000..458e203eb --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.rs @@ -0,0 +1,32 @@ +const _: () = { + trait X { + type Y<'a>; + } + + fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {} + //~^ ERROR: expected one of + }; + +const _: () = { + trait X { + type Y<'a>; + } + + trait Z {} + + impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {} + //~^ ERROR: expected one of +}; + +const _: () = { + trait X { + type Y<'a>; + } + + trait Z {} + + impl<T : X<X::Y<'a> = &'a u32>> Z for T {} + //~^ ERROR: expected one of +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr new file mode 100644 index 000000000..8bc737d67 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -0,0 +1,41 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:6:36 + | +LL | fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {} + | - ^ expected one of 8 possible tokens + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X<X::Y> = u32>>) {} + | + + +error: expected one of `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:17:35 + | +LL | impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {} + | - ^ expected one of `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl<T : X<<Self as X>::Y<'a>> = &'a u32>> Z for T {} + | + + +error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:28:25 + | +LL | impl<T : X<X::Y<'a> = &'a u32>> Z for T {} + | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl<T : X<X::Y<'a>> = &'a u32>> Z for T {} + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs new file mode 100644 index 000000000..1622b92aa --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -0,0 +1,11 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr new file mode 100644 index 000000000..0a09ec5dc --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -0,0 +1,33 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/trait-path-type-error-once-implemented.rs:6:29 + | +LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/trait-path-type-error-once-implemented.rs:2:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/trait-path-type-error-once-implemented.rs:6:29 + | +LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} + | ^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/trait-path-type-error-once-implemented.rs:2:10 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.rs b/tests/ui/generic-associated-types/parse/trait-path-types.rs new file mode 100644 index 000000000..74a00342f --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-types.rs @@ -0,0 +1,20 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {} + //~^ ERROR: expected one of +}; + +const _: () = { + fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {} + //~^ ERROR: expected one of +}; + +const _: () = { + fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {} + //~^ ERROR: expected one of +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.stderr b/tests/ui/generic-associated-types/parse/trait-path-types.stderr new file mode 100644 index 000000000..8f7a73c95 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-types.stderr @@ -0,0 +1,41 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:6:37 + | +LL | fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f<'a>(arg : Box<dyn X< [u8; 1]> = u32>>) {} + | + + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:11:37 + | +LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X<(Y<'a>)> = &'a ()>>) {} + | + + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:16:33 + | +LL | fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {} + | -- ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box<dyn X< 'a> = u32 >>) {} + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/pointer_family.rs b/tests/ui/generic-associated-types/pointer_family.rs new file mode 100644 index 000000000..80827cd56 --- /dev/null +++ b/tests/ui/generic-associated-types/pointer_family.rs @@ -0,0 +1,34 @@ +// check-pass + +use std::rc::Rc; +use std::sync::Arc; +use std::ops::Deref; + +trait PointerFamily { + type Pointer<T>: Deref<Target = T>; + fn new<T>(value: T) -> Self::Pointer<T>; +} + +struct ArcFamily; + +impl PointerFamily for ArcFamily { + type Pointer<T> = Arc<T>; + fn new<T>(value: T) -> Self::Pointer<T> { + Arc::new(value) + } +} + +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer<T> = Rc<T>; + fn new<T>(value: T) -> Self::Pointer<T> { + Rc::new(value) + } +} + +struct Foo<P: PointerFamily> { + bar: P::Pointer<String>, +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs b/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs new file mode 100644 index 000000000..ecf6f69c9 --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -0,0 +1,59 @@ +// Like `projection-bound-cycle.rs` but this avoids using +// `feature(trivial_bounds)`. + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where <Self as Foo>::Item: Sized; +} + +struct Number<T> { t: T } + +impl<T> Foo for Number<T> { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if ([T]: Sized) { # if the where clauses hold + // [T]: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item = [T] where [T]: Sized; + //~^ ERROR overflow evaluating the requirement `<Number<T> as Foo>::Item == _` +} + +struct OnlySized<T> where T: Sized { f: T } +impl<T> Print for OnlySized<T> { + fn print() { + println!("{}", std::mem::size_of::<T>()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl<T> Bar for T where T: Foo { + // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires + // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(<T as Foo>::Item)`, which is an invalid cycle. + type Assoc = OnlySized<<T as Foo>::Item>; +} + +fn foo<T: Print>() { + T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed +} + +fn bar<T: Bar>() { + // we have `FromEnv(T: Bar)` hence + // `<T as Bar>::Assoc` is well-formed and + // `Implemented(<T as Bar>::Assoc: Print)` hold + foo::<<T as Bar>::Assoc>() +} + +fn main() { + bar::<Number<u8>>() +} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr new file mode 100644 index 000000000..aae9a56bb --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `<Number<T> as Foo>::Item == _` + --> $DIR/projection-bound-cycle-generic.rs:23:5 + | +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/projection-bound-cycle.rs b/tests/ui/generic-associated-types/projection-bound-cycle.rs new file mode 100644 index 000000000..b51ae7ef2 --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle.rs @@ -0,0 +1,62 @@ +// Test case from Chalk. +// Make sure that we make sure that we don't allow arbitrary bounds to be +// proven when a bound and a where clause of an associated type are the same. + +#![feature(trivial_bounds)] + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where <Self as Foo>::Item: Sized; +} + +struct Number { } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if (str: Sized) { # if the where clauses hold + // str: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item = str where str: Sized; + //~^ ERROR overflow evaluating the requirement `<Number as Foo>::Item == _` +} + +struct OnlySized<T> where T: Sized { f: T } +impl<T> Print for OnlySized<T> { + fn print() { + println!("{}", std::mem::size_of::<T>()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl<T> Bar for T where T: Foo { + // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires + // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(<T as Foo>::Item)`, which is an invalid cycle. + type Assoc = OnlySized<<T as Foo>::Item>; +} + +fn foo<T: Print>() { + T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed +} + +fn bar<T: Bar>() { + // we have `FromEnv(T: Bar)` hence + // `<T as Bar>::Assoc` is well-formed and + // `Implemented(<T as Bar>::Assoc: Print)` hold + foo::<<T as Bar>::Assoc>() +} + +fn main() { + bar::<Number>() +} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle.stderr b/tests/ui/generic-associated-types/projection-bound-cycle.stderr new file mode 100644 index 000000000..b1b8afeec --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `<Number as Foo>::Item == _` + --> $DIR/projection-bound-cycle.rs:26:5 + | +LL | type Item = str where str: Sized; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs new file mode 100644 index 000000000..8e4d5ca5e --- /dev/null +++ b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs @@ -0,0 +1,33 @@ +pub trait X { + type Y<'a> where Self: 'a; + fn m(&self) -> Self::Y<'_>; +} + +impl X for () { + type Y<'a> = &'a (); + + fn m(&self) -> Self::Y<'_> { + self + } +} + +fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn h(x: &()) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn main() { + f(&()); + g(&()); + h(&()); +} diff --git a/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr new file mode 100644 index 000000000..753ead48b --- /dev/null +++ b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:15:5 + | +LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:20:5 + | +LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:25:5 + | +LL | fn h(x: &()) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/self-outlives-lint.rs b/tests/ui/generic-associated-types/self-outlives-lint.rs new file mode 100644 index 000000000..673891fc3 --- /dev/null +++ b/tests/ui/generic-associated-types/self-outlives-lint.rs @@ -0,0 +1,224 @@ +// check-fail + +use std::fmt::Debug; + +// We have a `&'a self`, so we need a `Self: 'a` +trait Iterable { + type Item<'x>; + //~^ missing required + fn iter<'a>(&'a self) -> Self::Item<'a>; +} + +/* +impl<T> Iterable for T { + type Item<'a> = &'a T; + fn iter<'a>(&'a self) -> Self::Item<'a> { + self + } +} +*/ + +// We have a `&'a T`, so we need a `T: 'x` +trait Deserializer<T> { + type Out<'x>; + //~^ missing required + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>; +} + +/* +impl<T> Deserializer<T> for () { + type Out<'a> = &'a T; + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input } +} +*/ + +// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x` +trait Deserializer2<T> { + type Out<'x>; + //~^ missing required + fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>; +} + +// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y` +trait Deserializer3<T, U> { + type Out<'x, 'y>; + //~^ missing required + fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>; +} + +// `T` is a param on the function, so it can't be named by the associated type +trait Deserializer4 { + type Out<'x>; + fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>; +} + +struct Wrap<T>(T); + +// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x` +trait Des { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>; +} +/* +impl Des for () { + type Out<'x, D> = &'x D; // Not okay + fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> { + data + } +} +*/ + +// We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an +// implied bound that `T: 'z`, so we require `D: 'x` +trait Des2 { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>; +} +/* +impl Des2 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> { + &data.0 + } +} +*/ + +// We see `&'z T`, so we require `D: 'x` +trait Des3 { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>; +} +/* +impl Des3 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> { + data + } +} +*/ + +// Similar case to before, except with GAT. +trait NoGat<'a> { + type Bar; + fn method(&'a self) -> Self::Bar; +} + +// Lifetime is not on function; except `Self: 'a` +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetime<'a> { + type Bar<'b>; + //~^ missing required + fn method(&'a self) -> Self::Bar<'a>; +} + +// Like above, but we have a where clause that can prove what we want +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetimeWhere<'a> where Self: 'a { + type Bar<'b>; + //~^ missing required + fn method(&'a self) -> Self::Bar<'a>; +} + +// Explicit bound instead of implicit; we want to still error +trait ExplicitBound { + type Bar<'b>; + //~^ missing required + fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b; +} + +// The use of the GAT here is not in the return, we don't want to error +trait NotInReturn { + type Bar<'b>; + fn method<'b>(&'b self) where Self::Bar<'b>: Debug; +} + +// We obviously error for `Iterator`, but we should also error for `Item` +trait IterableTwo { + type Item<'a>; + //~^ missing required + type Iterator<'a>: Iterator<Item = Self::Item<'a>>; + //~^ missing required + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} + +trait IterableTwoWhere { + type Item<'a>; + //~^ missing required + type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a; + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} + +// We also should report region outlives clauses. Here, we know that `'y: 'x`, +// because of `&'x &'y`, so we require that `'b: 'a`. +trait RegionOutlives { + type Bar<'a, 'b>; + //~^ missing required + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>; +} + +/* +impl Foo for () { + type Bar<'a, 'b> = &'a &'b (); + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> { + input + } +} +*/ + +// Similar to the above, except with explicit bounds +trait ExplicitRegionOutlives<'ctx> { + type Fut<'out>; + //~^ missing required + + fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out> + where + 'ctx: 'out; +} + + +// If there are multiple methods that return the GAT, require a set of clauses +// that can be satisfied by *all* methods +trait MultipleMethods { + type Bar<'me>; + + fn gimme<'a>(&'a self) -> Self::Bar<'a>; + fn gimme_default(&self) -> Self::Bar<'static>; +} + +// We would normally require `Self: 'a`, but we can prove that `Self: 'static` +// because of the the bounds on the trait, so the bound is proven +trait Trait: 'static { + type Assoc<'a>; + fn make_assoc(_: &u32) -> Self::Assoc<'_>; +} + +// We ignore `'static` lifetimes for any lints +trait StaticReturn<'a> { + type Y<'b>; + fn foo(&self) -> Self::Y<'static>; +} + +// Same as above, but with extra method that takes GAT - just make sure this works +trait StaticReturnAndTakes<'a> { + type Y<'b>; + fn foo(&self) -> Self::Y<'static>; + fn bar<'b>(&self, arg: Self::Y<'b>); +} + +// We require bounds when the GAT appears in the inputs +trait Input { + type Item<'a>; + //~^ missing required + fn takes_item<'a>(&'a self, item: Self::Item<'a>); +} + +// We don't require bounds when the GAT appears in the where clauses +trait WhereClause { + type Item<'a>; + fn takes_item<'a>(&'a self) where Self::Item<'a>: ; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/self-outlives-lint.stderr b/tests/ui/generic-associated-types/self-outlives-lint.stderr new file mode 100644 index 000000000..9e9b2e18a --- /dev/null +++ b/tests/ui/generic-associated-types/self-outlives-lint.stderr @@ -0,0 +1,178 @@ +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:7:5 + | +LL | type Item<'x>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:23:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where T: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:37:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where T: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bounds on `Out` + --> $DIR/self-outlives-lint.rs:44:5 + | +LL | type Out<'x, 'y>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where T: 'x, U: 'y` + | + = note: these bounds are currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:59:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:75:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:90:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bounds on `Bar` + --> $DIR/self-outlives-lint.rs:112:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a, Self: 'b` + | + = note: these bounds are currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:120:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'b` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:127:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'b` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Iterator` + --> $DIR/self-outlives-lint.rs:142:5 + | +LL | type Iterator<'a>: Iterator<Item = Self::Item<'a>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:140:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:148:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:157:5 + | +LL | type Bar<'a, 'b>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where 'b: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Fut` + --> $DIR/self-outlives-lint.rs:173:5 + | +LL | type Fut<'out>; + | ^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where 'ctx: 'out` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:213:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information + +error: aborting due to 16 previous errors + diff --git a/tests/ui/generic-associated-types/shadowing.rs b/tests/ui/generic-associated-types/shadowing.rs new file mode 100644 index 000000000..a05d6e143 --- /dev/null +++ b/tests/ui/generic-associated-types/shadowing.rs @@ -0,0 +1,29 @@ +trait Shadow<'a> { + type Bar<'a>; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope +} + +trait NoShadow<'a> { + type Bar<'b>; // OK +} + +impl<'a> NoShadow<'a> for &'a u32 { + type Bar<'a> = i32; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope +} + +trait ShadowT<T> { + type Bar<T>; + //~^ ERROR the name `T` is already used +} + +trait NoShadowT<T> { + type Bar<U>; // OK +} + +impl<T> NoShadowT<T> for Option<T> { + type Bar<T> = i32; + //~^ ERROR the name `T` is already used +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/shadowing.stderr b/tests/ui/generic-associated-types/shadowing.stderr new file mode 100644 index 000000000..bb32684bc --- /dev/null +++ b/tests/ui/generic-associated-types/shadowing.stderr @@ -0,0 +1,36 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:2:14 + | +LL | trait Shadow<'a> { + | -- first declared here +LL | type Bar<'a>; + | ^^ lifetime `'a` already in scope + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:11:14 + | +LL | impl<'a> NoShadow<'a> for &'a u32 { + | -- first declared here +LL | type Bar<'a> = i32; + | ^^ lifetime `'a` already in scope + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:16:14 + | +LL | trait ShadowT<T> { + | - first use of `T` +LL | type Bar<T>; + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:25:14 + | +LL | impl<T> NoShadowT<T> for Option<T> { + | - first use of `T` +LL | type Bar<T> = i32; + | ^ already used + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0403, E0496. +For more information about an error, try `rustc --explain E0403`. diff --git a/tests/ui/generic-associated-types/streaming_iterator.rs b/tests/ui/generic-associated-types/streaming_iterator.rs new file mode 100644 index 000000000..408b8dc99 --- /dev/null +++ b/tests/ui/generic-associated-types/streaming_iterator.rs @@ -0,0 +1,74 @@ +// run-pass + +use std::fmt::Display; + +trait StreamingIterator { + type Item<'a> where Self: 'a; + // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. + fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>; +} + +struct Foo<T: StreamingIterator + 'static> { + // Applying a concrete lifetime to the constructor outside the trait. + bar: <T as StreamingIterator>::Item<'static>, +} + +// Users can bound parameters by the type constructed by that trait's associated type constructor +// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid: +//FIXME(#44265): This next line should parse and be valid +//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(_iter: T) { /* ... */ } +fn _foo<T>(_iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } + +// Full example of enumerate iterator + +#[must_use = "iterators are lazy and do nothing unless consumed"] +struct StreamEnumerate<I> { + iter: I, + count: usize, +} + +impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> { + type Item<'a> = (usize, I::Item<'a>) where Self: 'a; + fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> { + match self.iter.next() { + None => None, + Some(val) => { + let r = Some((self.count, val)); + self.count += 1; + r + } + } + } +} + +impl<I: Iterator> StreamingIterator for I { + type Item<'a> = <I as Iterator>::Item where Self: 'a; + fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> { + Iterator::next(self) + } +} + +impl<I> StreamEnumerate<I> { + pub fn new(iter: I) -> Self { + StreamEnumerate { + count: 0, + iter, + } + } +} + +fn test_stream_enumerate() { + let v = vec!["a", "b", "c"]; + let mut se = StreamEnumerate::new(v.iter()); + while let Some(item) = se.next() { + assert_eq!(v[item.0], *item.1); + } + let x = Foo::<std::slice::Iter<'static, u32>> { + bar: &0u32, + }; + assert_eq!(*x.bar, 0u32); +} + +fn main() { + test_stream_enumerate(); +} diff --git a/tests/ui/generic-associated-types/trait-objects.base.stderr b/tests/ui/generic-associated-types/trait-objects.base.stderr new file mode 100644 index 000000000..556422c27 --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:13:21 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/trait-objects.rs:7:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/trait-objects.extended.stderr b/tests/ui/generic-associated-types/trait-objects.extended.stderr new file mode 100644 index 000000000..45b64d2b0 --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.extended.stderr @@ -0,0 +1,19 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/trait-objects.rs:15:5 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the function body +LL | +LL | x.size_hint().0 + | ^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs new file mode 100644 index 000000000..17fed11ba --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -0,0 +1,19 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait StreamingIterator { + type Item<'a> where Self: 'a; + fn size_hint(&self) -> (usize, Option<usize>); + // Uncommenting makes `StreamingIterator` not object safe +// fn next(&mut self) -> Self::Item<'_>; +} + +fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + //[base]~^ the trait `StreamingIterator` cannot be made into an object + x.size_hint().0 + //[extended]~^ borrowed data escapes +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/type-param-defaults.rs b/tests/ui/generic-associated-types/type-param-defaults.rs new file mode 100644 index 000000000..f034076b0 --- /dev/null +++ b/tests/ui/generic-associated-types/type-param-defaults.rs @@ -0,0 +1,34 @@ +// Check that we disallow GAT param defaults, even with `invalid_type_param_default` allowed + +#![allow(invalid_type_param_default)] + +trait Trait { + type Assoc<T = u32>; + //~^ defaults for type parameters are only allowed +} + +impl Trait for () { + type Assoc<T = u32> = u64; + //~^ defaults for type parameters are only allowed +} + +impl Trait for u32 { + type Assoc<T = u32> = T; + //~^ defaults for type parameters are only allowed +} + +trait Other {} +impl Other for u32 {} + +fn foo<T>() +where + T: Trait<Assoc = u32>, + T::Assoc: Other { + } + +fn main() { + // errors + foo::<()>(); + // works + foo::<u32>(); +} diff --git a/tests/ui/generic-associated-types/type-param-defaults.stderr b/tests/ui/generic-associated-types/type-param-defaults.stderr new file mode 100644 index 000000000..85ccaba0e --- /dev/null +++ b/tests/ui/generic-associated-types/type-param-defaults.stderr @@ -0,0 +1,20 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:6:16 + | +LL | type Assoc<T = u32>; + | ^^^^^^^ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:11:16 + | +LL | type Assoc<T = u32> = u64; + | ^^^^^^^ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:16:16 + | +LL | type Assoc<T = u32> = T; + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs new file mode 100644 index 000000000..1cc09aa6d --- /dev/null +++ b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs @@ -0,0 +1,25 @@ +pub trait X { + type Y<'a: 'static>; + //~^ WARNING unnecessary lifetime parameter +} + +impl X for () { + type Y<'a> = &'a (); +} + +struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> { + f: <T as X>::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +struct C<'a, T: X> { + f: <T as X>::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +struct D<'a> { + f: <() as X>::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr new file mode 100644 index 000000000..fbd79879d --- /dev/null +++ b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr @@ -0,0 +1,50 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/unsatified-item-lifetime-bound.rs:2:12 + | +LL | type Y<'a: 'static>; + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:11:8 + | +LL | f: <T as X>::Y<'a>, + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:10:10 + | +LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:16:8 + | +LL | f: <T as X>::Y<'a>, + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:15:10 + | +LL | struct C<'a, T: X> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:21:8 + | +LL | f: <() as X>::Y<'a>, + | ^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:20:10 + | +LL | struct D<'a> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs new file mode 100644 index 000000000..7137d9237 --- /dev/null +++ b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -0,0 +1,19 @@ +trait ATy { + type Item<'a>: 'a; +} + +impl<'b> ATy for &'b () { + type Item<'a> = &'b (); + //~^ ERROR the type `&'b ()` does not fulfill the required lifetime +} + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); + //~^ ERROR the type `&'a ()` does not fulfill the required lifetime +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr new file mode 100644 index 000000000..1c9ac01ec --- /dev/null +++ b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -0,0 +1,27 @@ +error[E0477]: the type `&'b ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:6:21 + | +LL | type Item<'a> = &'b (); + | ^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here as required by this binding + --> $DIR/unsatisfied-outlives-bound.rs:6:15 + | +LL | type Item<'a> = &'b (); + | ^^ + +error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:15:21 + | +LL | type Item<'a> = &'a (); + | ^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/unsatisfied-outlives-bound.rs:11:20 + | +LL | type Item<'a>: 'static; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/variance_constraints.rs b/tests/ui/generic-associated-types/variance_constraints.rs new file mode 100644 index 000000000..0e9dbb8b1 --- /dev/null +++ b/tests/ui/generic-associated-types/variance_constraints.rs @@ -0,0 +1,22 @@ +// check-pass +// issue #69184 + +trait A { + type B<'a> where Self: 'a; + + fn make_b<'a>(&'a self) -> Self::B<'a>; +} + +struct S {} +impl A for S { + type B<'a> = &'a S; + fn make_b<'a>(&'a self) -> &'a Self { + self + } +} + +enum E<'a> { + S(<S as A>::B<'a>), +} + +fn main() {} |