diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/generic-associated-types | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
237 files changed, 6619 insertions, 0 deletions
diff --git a/src/test/ui/generic-associated-types/anonymize-bound-vars.rs b/src/test/ui/generic-associated-types/anonymize-bound-vars.rs new file mode 100644 index 000000000..1ec9c6998 --- /dev/null +++ b/src/test/ui/generic-associated-types/anonymize-bound-vars.rs @@ -0,0 +1,14 @@ +// check-pass +// +// regression test for #98702 +#![feature(generic_associated_types)] + +trait Foo { + type Assoc<T>; +} + +impl Foo for () { + type Assoc<T> = [T; 2*2]; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs new file mode 100644 index 000000000..0e8e14852 --- /dev/null +++ b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs @@ -0,0 +1,8 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs new file mode 100644 index 000000000..14f27aff1 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -0,0 +1,17 @@ +// check-fail +// known-bug: #80626 + +// This should pass, but it requires `Sized` to be coinductive. + +#![feature(generic_associated_types)] + +trait Allocator { + type Allocated<T>; +} + +enum LinkedList<A: Allocator> { + Head, + Next(A::Allocated<Self>) +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr new file mode 100644 index 000000000..487b83dfa --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized` + --> $DIR/issue-80626.rs:14:10 + | +LL | Next(A::Allocated<Self>) + | ^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `Allocator::Allocated` + --> $DIR/issue-80626.rs:9:20 + | +LL | type Allocated<T>; + | ^ required by this bound in `Allocator::Allocated` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs new file mode 100644 index 000000000..fb62c10a9 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs @@ -0,0 +1,27 @@ +// check-fail +// known-bug: #86218 + +// This should pass, but seems to run into a TAIT issue. + +#![feature(generic_associated_types)] +#![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; + fn foo<'s>() -> Self::InnerStream<'s> { todo!() } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr new file mode 100644 index 000000000..fbf1c8f95 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -0,0 +1,23 @@ +error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime + --> $DIR/issue-86218.rs:23:28 + | +LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'s` as defined here as required by this binding + --> $DIR/issue-86218.rs:23:22 + | +LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; + | ^^ + +error: unconstrained opaque type + --> $DIR/issue-86218.rs:23:28 + | +LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `InnerStream` must be used in combination with a concrete type within the same module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs new file mode 100644 index 000000000..0844d84c3 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -0,0 +1,46 @@ +// check-fail +// known-bug: #87735, #88526 + +// This should pass, but we need an extension of implied bounds (probably). + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr new file mode 100644 index 000000000..0a18b5f0c --- /dev/null +++ b/src/test/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:27: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/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs new file mode 100644 index 000000000..a3d00ee03 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -0,0 +1,23 @@ +// check-fail +// known-bug: #87748 + +// This should pass, but unnormalized input args aren't treated as implied. + +#![feature(generic_associated_types)] + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); +} + +struct Foo; + +impl MyTrait for Foo { + type Assoc<'a, 'b> = u32 where 'b: 'a; + + fn do_sth(_: u32) {} + // fn do_sth(_: Self::Assoc<'static, 'static>) {} + // fn do_sth(_: Self::Assoc<'_, '_>) {} +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr new file mode 100644 index 000000000..ac197dfe6 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -0,0 +1,20 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-87748.rs:18:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/issue-87748.rs:18:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ +note: but lifetime parameter must outlive the anonymous lifetime as defined here + --> $DIR/issue-87748.rs:18:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs new file mode 100644 index 000000000..efa487d62 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs @@ -0,0 +1,21 @@ +// check-fail +// known-bug: #87755 + +// This should pass. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-87755.stderr b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr new file mode 100644 index 000000000..5d1aff011 --- /dev/null +++ b/src/test/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:18:16 + | +LL | type Ass = Bar; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs new file mode 100644 index 000000000..a8a111c99 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs @@ -0,0 +1,27 @@ +// check-fail +// known-bug: #87803 + +// This should pass, but using a type alias vs a reference directly +// changes late-bound -> early-bound. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-87803.stderr b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr new file mode 100644 index 000000000..c81c051d3 --- /dev/null +++ b/src/test/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:22: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/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs new file mode 100644 index 000000000..5493b9b93 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs @@ -0,0 +1,31 @@ +// check-fail +// known-bug: #88382 + +// This should pass, but has a missed normalization due to HRTB. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr new file mode 100644 index 000000000..7210895b7 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-88382.rs:28: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<'r> fn(&'r mut std::iter::Empty<usize>) -> _` + found function signature `for<'a, 'r> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _` +note: required by a bound in `do_something` + --> $DIR/issue-88382.rs:22: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/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs new file mode 100644 index 000000000..f1c3b2269 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -0,0 +1,31 @@ +// check-fail +// known-bug: #88460 + +// This should pass, but has a missed normalization due to HRTB. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr new file mode 100644 index 000000000..98c304cc9 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied + --> $DIR/issue-88460.rs:30:5 + | +LL | test(Foo); + | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` + | + = help: the trait `Marker` is implemented for `()` +note: required by a bound in `test` + --> $DIR/issue-88460.rs:17: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/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs new file mode 100644 index 000000000..15363ad04 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs @@ -0,0 +1,35 @@ +// check-fail +// known-bug: #88526 + +// This should pass, but requires more logic. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/bugs/issue-88526.stderr b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr new file mode 100644 index 000000000..127c889bf --- /dev/null +++ b/src/test/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:27: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/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs new file mode 100644 index 000000000..79c28b0d2 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs @@ -0,0 +1,44 @@ +// check-fail +// edition:2021 +// known-bug: #88908 + +// This should pass, but seems to run into a TAIT bug. + +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +use std::future::Future; + +trait Stream { + type Item; +} + +struct Empty<T>(T); +impl<T> Stream for Empty<T> { + type Item = (); +} +fn empty<T>() -> Empty<T> { + todo!() +} + +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()} + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr new file mode 100644 index 000000000..50844fdc1 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr @@ -0,0 +1,19 @@ +error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr` + --> $DIR/issue-89008.rs:39:43 + | +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr` + | | + | this type parameter + | +note: expected this to be `()` + --> $DIR/issue-89008.rs:18:17 + | +LL | type Item = (); + | ^^ + = note: expected unit type `()` + found type parameter `Repr` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs new file mode 100644 index 000000000..157e1b1d2 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -0,0 +1,71 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr new file mode 100644 index 000000000..22fbc0271 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/collections-project-default.rs:59: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/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs new file mode 100644 index 000000000..1c00aa73f --- /dev/null +++ b/src/test/ui/generic-associated-types/collections.rs @@ -0,0 +1,70 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/collectivity-regression.rs b/src/test/ui/generic-associated-types/collectivity-regression.rs new file mode 100644 index 000000000..fb7368439 --- /dev/null +++ b/src/test/ui/generic-associated-types/collectivity-regression.rs @@ -0,0 +1,24 @@ +// Regression test from https://github.com/rust-lang/rust/pull/98109 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/collectivity-regression.stderr b/src/test/ui/generic-associated-types/collectivity-regression.stderr new file mode 100644 index 000000000..a858dd7fd --- /dev/null +++ b/src/test/ui/generic-associated-types/collectivity-regression.stderr @@ -0,0 +1,14 @@ +error: `T` does not live long enough + --> $DIR/collectivity-regression.rs:15:5 + | +LL | / || { +LL | | +LL | | // +LL | | // FIXME(#98437). This regressed at some point and +LL | | // probably should work. +LL | | let _x = x; +LL | | }; + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs new file mode 100644 index 000000000..afde5f376 --- /dev/null +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs new file mode 100644 index 000000000..51046be79 --- /dev/null +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs new file mode 100644 index 000000000..457fe27b3 --- /dev/null +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs @@ -0,0 +1,26 @@ +// run-pass +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/const_params_have_right_type.rs b/src/test/ui/generic-associated-types/const_params_have_right_type.rs new file mode 100644 index 000000000..6bed8e3af --- /dev/null +++ b/src/test/ui/generic-associated-types/const_params_have_right_type.rs @@ -0,0 +1,12 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/const_params_have_right_type.stderr b/src/test/ui/generic-associated-types/const_params_have_right_type.stderr new file mode 100644 index 000000000..89c993dee --- /dev/null +++ b/src/test/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:8: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/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs new file mode 100644 index 000000000..e315ee842 --- /dev/null +++ b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs @@ -0,0 +1,16 @@ +// Test that correct syntax is used in suggestion to constrain associated type + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr new file mode 100644 index 000000000..957ae5d29 --- /dev/null +++ b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/constraint-assoc-type-suggestion.rs:12: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/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs new file mode 100644 index 000000000..060804269 --- /dev/null +++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs @@ -0,0 +1,24 @@ +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/cross-crate-bounds.rs b/src/test/ui/generic-associated-types/cross-crate-bounds.rs new file mode 100644 index 000000000..8934a07fd --- /dev/null +++ b/src/test/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/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr new file mode 100644 index 000000000..c4009dd96 --- /dev/null +++ b/src/test/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:6:15 + | +LL | type Bar: AsRef<()>; + | ^^^^^^^^^ required by this bound in `foo_defn::Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/elided-in-expr-position.rs b/src/test/ui/generic-associated-types/elided-in-expr-position.rs new file mode 100644 index 000000000..482d0d5c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/elided-in-expr-position.rs @@ -0,0 +1,38 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/elided-in-expr-position.stderr b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr new file mode 100644 index 000000000..b395a1cfd --- /dev/null +++ b/src/test/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:10: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:5:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'a>; + | ~~~~~~~~~ + +error[E0107]: missing generics for associated type `Trait::Assoc` + --> $DIR/elided-in-expr-position.rs:32: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:5:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'a> { + | ~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/empty_generics.rs b/src/test/ui/generic-associated-types/empty_generics.rs new file mode 100644 index 000000000..772b7f2b4 --- /dev/null +++ b/src/test/ui/generic-associated-types/empty_generics.rs @@ -0,0 +1,8 @@ +#![feature(generic_associated_types)] + +trait Foo { + type Bar<,>; + //~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr new file mode 100644 index 000000000..ac22bfc08 --- /dev/null +++ b/src/test/ui/generic-associated-types/empty_generics.stderr @@ -0,0 +1,13 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/empty_generics.rs:4: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/src/test/ui/generic-associated-types/equality-bound.rs b/src/test/ui/generic-associated-types/equality-bound.rs new file mode 100644 index 000000000..fcc2da801 --- /dev/null +++ b/src/test/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/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr new file mode 100644 index 000000000..d78f7a7fb --- /dev/null +++ b/src/test/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/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr new file mode 100644 index 000000000..3da7794b3 --- /dev/null +++ b/src/test/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:14: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/src/test/ui/generic-associated-types/extended/lending_iterator.rs b/src/test/ui/generic-associated-types/extended/lending_iterator.rs new file mode 100644 index 000000000..ede164766 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.rs @@ -0,0 +1,39 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr new file mode 100644 index 000000000..6c2a624ca --- /dev/null +++ b/src/test/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:14: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/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs new file mode 100644 index 000000000..3c4a2184d --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -0,0 +1,31 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs new file mode 100644 index 000000000..c1d68812e --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs @@ -0,0 +1,16 @@ +// rust-lang/rust#60654: Do not ICE on an attempt to use GATs that is +// missing the feature gate. + +struct Foo; + +trait MyTrait { + type Item<T>; + //~^ ERROR generic associated types are unstable [E0658] +} + +impl MyTrait for Foo { + type Item<T> = T; + //~^ ERROR generic associated types are unstable [E0658] +} + +fn main() { } diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr new file mode 100644 index 000000000..34f536dbe --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr @@ -0,0 +1,21 @@ +error[E0658]: generic associated types are unstable + --> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5 + | +LL | type Item<T>; + | ^^^^^^^^^^^^^ + | + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error[E0658]: generic associated types are unstable + --> $DIR/gat-dont-ice-on-absent-feature-2.rs:12:5 + | +LL | type Item<T> = T; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs new file mode 100644 index 000000000..e8fc47d2a --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs @@ -0,0 +1,16 @@ +// rust-lang/rust#60654: Do not ICE on an attempt to use GATs that is +// missing the feature gate. + +struct Foo; + +impl Iterator for Foo { + type Item<'b> = &'b Foo; + //~^ ERROR generic associated types are unstable [E0658] + //~| ERROR lifetime parameters or bounds on type `Item` do not match the trait declaration + + fn next(&mut self) -> Option<Self::Item> { + None + } +} + +fn main() { } diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr new file mode 100644 index 000000000..ec36886f7 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr @@ -0,0 +1,19 @@ +error[E0658]: generic associated types are unstable + --> $DIR/gat-dont-ice-on-absent-feature.rs:7:5 + | +LL | type Item<'b> = &'b Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration + --> $DIR/gat-dont-ice-on-absent-feature.rs:7:14 + | +LL | type Item<'b> = &'b Foo; + | ^^^^ lifetimes do not match type in trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0195, E0658. +For more information about an error, try `rustc --explain E0195`. diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs new file mode 100644 index 000000000..f542a7f54 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -0,0 +1,11 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr new file mode 100644 index 000000000..1792d8db2 --- /dev/null +++ b/src/test/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:8: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:8: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/src/test/ui/generic-associated-types/gat-in-trait-path.base.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.base.stderr new file mode 100644 index 000000000..c2054f64e --- /dev/null +++ b/src/test/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:27: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:11: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/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs new file mode 100644 index 000000000..c82450ccf --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -0,0 +1,34 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/gat-incomplete-warning.rs b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs new file mode 100644 index 000000000..607ea1759 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs @@ -0,0 +1,5 @@ +// run-pass + +#![feature(generic_associated_types)] + +fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs new file mode 100644 index 000000000..dbf7e02ae --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -0,0 +1,16 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr new file mode 100644 index 000000000..dad0dae6a --- /dev/null +++ b/src/test/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:11: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:11: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:9: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/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs new file mode 100644 index 000000000..9864787f0 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -0,0 +1,17 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr new file mode 100644 index 000000000..aeb9238de --- /dev/null +++ b/src/test/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:10: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:4: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:10: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:4: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/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs new file mode 100644 index 000000000..c55b0530c --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -0,0 +1,18 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr new file mode 100644 index 000000000..162214063 --- /dev/null +++ b/src/test/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:7: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:7: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:14: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:7: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:4:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:7: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:4: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:14: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:4:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {} + | ++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs new file mode 100644 index 000000000..d7c4dbda2 --- /dev/null +++ b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs new file mode 100644 index 000000000..2ecbc8c59 --- /dev/null +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs @@ -0,0 +1,28 @@ +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr new file mode 100644 index 000000000..e866b3bab --- /dev/null +++ b/src/test/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:20: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:22: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/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs new file mode 100644 index 000000000..43058f7eb --- /dev/null +++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -0,0 +1,15 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr new file mode 100644 index 000000000..a4bb36190 --- /dev/null +++ b/src/test/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:8: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:11: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/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs new file mode 100644 index 000000000..ec1d171c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -0,0 +1,26 @@ +#![feature(generic_associated_types)] +#![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 + //~| ERROR lifetime bound not satisfied + 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/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr new file mode 100644 index 000000000..ce79c635a --- /dev/null +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -0,0 +1,92 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:15: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:17: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` + +error[E0478]: lifetime bound not satisfied + --> $DIR/impl_bounds.rs:17:22 + | +LL | type B<'a, 'b> where 'a: 'b; + | -------------- definition of `B` from trait +... +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b` + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/impl_bounds.rs:17:12 + | +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here + --> $DIR/impl_bounds.rs:17:16 + | +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + | ^^ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/impl_bounds.rs:20:33 + | +LL | type C = String where Self: Copy; + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required because of the requirements on the impl of `Copy` for `Fooy<T>` + --> $DIR/impl_bounds.rs:11:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +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:7: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:22:24 + | +LL | fn d() where Self: Copy {} + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required because of the requirements on the impl of `Copy` for `Fooy<T>` + --> $DIR/impl_bounds.rs:11:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +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:8: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 5 previous errors + +Some errors have detailed explanations: E0276, E0277, E0478. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs new file mode 100644 index 000000000..4df8235d9 --- /dev/null +++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs new file mode 100644 index 000000000..d352c1948 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs @@ -0,0 +1,16 @@ +// Check that this program doesn't cause the compiler to error without output. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr new file mode 100644 index 000000000..31948a878 --- /dev/null +++ b/src/test/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:12: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/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs new file mode 100644 index 000000000..e87a76825 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Cert { + type PublicKey<'a>: From<&'a [u8]>; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs new file mode 100644 index 000000000..d74d6d056 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -0,0 +1,13 @@ +#![feature(generic_associated_types)] + +// check-pass + +trait Iterator { + type Item<'a>: 'a; +} + +impl Iterator for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs new file mode 100644 index 000000000..fa35a3e8b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.rs @@ -0,0 +1,12 @@ +// Fixed by #67160 + +trait Trait1 { + type A; +} + +trait Trait2 { + type Type1<B>: Trait1<A=B>; + //~^ ERROR: generic associated types are unstable +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr new file mode 100644 index 000000000..bbb7d56f5 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.stderr @@ -0,0 +1,12 @@ +error[E0658]: generic associated types are unstable + --> $DIR/issue-67424.rs:8:5 + | +LL | type Type1<B>: Trait1<A=B>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.base.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.base.stderr new file mode 100644 index 000000000..74a616aaa --- /dev/null +++ b/src/test/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:13: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:10: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/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs new file mode 100644 index 000000000..c5b02ff9a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -0,0 +1,16 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-67510.rs b/src/test/ui/generic-associated-types/issue-67510.rs new file mode 100644 index 000000000..5725b660a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510.rs @@ -0,0 +1,12 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-67510.stderr b/src/test/ui/generic-associated-types/issue-67510.stderr new file mode 100644 index 000000000..8aeda22ba --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510.stderr @@ -0,0 +1,50 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:7: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:7: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:7: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:4: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/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs new file mode 100644 index 000000000..617d985dc --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -0,0 +1,31 @@ +// Regression test for #68641 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr new file mode 100644 index 000000000..2e21b38cb --- /dev/null +++ b/src/test/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:14: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:6: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/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs new file mode 100644 index 000000000..def0ad18f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -0,0 +1,20 @@ +// Regression test for #68642 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr new file mode 100644 index 000000000..713cc744f --- /dev/null +++ b/src/test/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:14: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:6: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/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs new file mode 100644 index 000000000..9af065b5d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -0,0 +1,20 @@ +// Regression test for #68643 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr new file mode 100644 index 000000000..a7b7f64cd --- /dev/null +++ b/src/test/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:14: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:6: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/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs new file mode 100644 index 000000000..1d2636c26 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -0,0 +1,20 @@ +// Regression test for #68644 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr new file mode 100644 index 000000000..5e921e053 --- /dev/null +++ b/src/test/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:14: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:6: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/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs new file mode 100644 index 000000000..aa505064f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -0,0 +1,20 @@ +// Regression test for #68645 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr new file mode 100644 index 000000000..7edcdce62 --- /dev/null +++ b/src/test/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:14: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:6: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/src/test/ui/generic-associated-types/issue-68648-1.rs b/src/test/ui/generic-associated-types/issue-68648-1.rs new file mode 100644 index 000000000..17bc034b3 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-1.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(generic_associated_types)] + + +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/src/test/ui/generic-associated-types/issue-68648-2.rs b/src/test/ui/generic-associated-types/issue-68648-2.rs new file mode 100644 index 000000000..6c9a0d126 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-2.rs @@ -0,0 +1,23 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68648-2.stderr b/src/test/ui/generic-associated-types/issue-68648-2.stderr new file mode 100644 index 000000000..06c1efcd8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-2.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-68648-2.rs:14: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:6: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/src/test/ui/generic-associated-types/issue-68649-pass.rs b/src/test/ui/generic-associated-types/issue-68649-pass.rs new file mode 100644 index 000000000..33f08faff --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68649-pass.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68653.rs b/src/test/ui/generic-associated-types/issue-68653.rs new file mode 100644 index 000000000..1e84717e9 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68653.rs @@ -0,0 +1,15 @@ +// A regression test for #68653, which was fixed by #68938. + +// check-pass + +#![feature(generic_associated_types)] + +trait Fun { + type F<'a: 'a>; +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs new file mode 100644 index 000000000..c0d933362 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -0,0 +1,21 @@ +// Regression test for #68656 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr new file mode 100644 index 000000000..8e0f23716 --- /dev/null +++ b/src/test/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:15: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:6: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/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs new file mode 100644 index 000000000..568996e1a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70303.rs @@ -0,0 +1,59 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-70304.rs b/src/test/ui/generic-associated-types/issue-70304.rs new file mode 100644 index 000000000..f778f985c --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70304.rs @@ -0,0 +1,57 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-70304.stderr b/src/test/ui/generic-associated-types/issue-70304.stderr new file mode 100644 index 000000000..bba7cab70 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70304.stderr @@ -0,0 +1,33 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-70304.rs:48:41 + | +LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + | ^^ `'_` is a reserved lifetime name + +error[E0106]: missing lifetime specifier + --> $DIR/issue-70304.rs:48: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:4: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/src/test/ui/generic-associated-types/issue-71176.rs b/src/test/ui/generic-associated-types/issue-71176.rs new file mode 100644 index 000000000..c2f0d59f4 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-71176.rs @@ -0,0 +1,20 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr new file mode 100644 index 000000000..08c8d4162 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-71176.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:12: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:4: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/src/test/ui/generic-associated-types/issue-74684-1.rs b/src/test/ui/generic-associated-types/issue-74684-1.rs new file mode 100644 index 000000000..0e3899a88 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-1.rs @@ -0,0 +1,25 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-74684-1.stderr b/src/test/ui/generic-associated-types/issue-74684-1.stderr new file mode 100644 index 000000000..2cd050ed8 --- /dev/null +++ b/src/test/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:15: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/src/test/ui/generic-associated-types/issue-74684-2.rs b/src/test/ui/generic-associated-types/issue-74684-2.rs new file mode 100644 index 000000000..fca55070b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-2.rs @@ -0,0 +1,25 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr new file mode 100644 index 000000000..f0e03e73f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + --> $DIR/issue-74684-2.rs:23:5 + | +LL | bug(Box::new(x)); + | ^^^ type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + | +note: expected this to be `[u8]` + --> $DIR/issue-74684-2.rs:10:18 + | +LL | type F<'a> = i32; + | ^^^ +note: required by a bound in `bug` + --> $DIR/issue-74684-2.rs:13: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/src/test/ui/generic-associated-types/issue-74816.rs b/src/test/ui/generic-associated-types/issue-74816.rs new file mode 100644 index 000000000..c932025d1 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74816.rs @@ -0,0 +1,22 @@ +#![feature(associated_type_defaults)] +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-74816.stderr b/src/test/ui/generic-associated-types/issue-74816.stderr new file mode 100644 index 000000000..9eaa74e34 --- /dev/null +++ b/src/test/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:9: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:9: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:9: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:9: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/src/test/ui/generic-associated-types/issue-74824.rs b/src/test/ui/generic-associated-types/issue-74824.rs new file mode 100644 index 000000000..1bbf7aac5 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74824.rs @@ -0,0 +1,26 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr new file mode 100644 index 000000000..8517eb9fa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74824.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `Box<T>: Copy` is not satisfied + --> $DIR/issue-74824.rs:7: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:7: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:7:26 + | +LL | type Copy<T>: Copy = Box<T>; + | ^^^^^^ the trait `Clone` is not implemented for `T` + | + = note: required because of the requirements on the impl of `Clone` for `Box<T>` +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:7: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/src/test/ui/generic-associated-types/issue-76407.rs b/src/test/ui/generic-associated-types/issue-76407.rs new file mode 100644 index 000000000..a8141829b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76407.rs @@ -0,0 +1,27 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-76535.base.stderr b/src/test/ui/generic-associated-types/issue-76535.base.stderr new file mode 100644 index 000000000..5decd58bb --- /dev/null +++ b/src/test/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:40: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:10: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:40: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:10: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:40: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:10: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 because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>` + = 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/src/test/ui/generic-associated-types/issue-76535.extended.stderr b/src/test/ui/generic-associated-types/issue-76535.extended.stderr new file mode 100644 index 000000000..067d0489b --- /dev/null +++ b/src/test/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:40: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:10: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/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs new file mode 100644 index 000000000..46f217ba0 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -0,0 +1,44 @@ +// revisions: base extended + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-76826.rs b/src/test/ui/generic-associated-types/issue-76826.rs new file mode 100644 index 000000000..28eb3b0e7 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76826.rs @@ -0,0 +1,44 @@ +// run-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs new file mode 100644 index 000000000..850d83be6 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs @@ -0,0 +1,40 @@ +// Test for diagnostics when we have mismatched lifetime due to implict 'static lifetime in GATs + +// check-fail + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr new file mode 100644 index 000000000..d487f19ba --- /dev/null +++ b/src/test/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:17: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:12: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:17: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:9: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:27: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:23: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:27: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:21:1 + | +LL | impl C for Box<dyn A + 'static> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37: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:33: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:37: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:31: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:31: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/src/test/ui/generic-associated-types/issue-78671.base.stderr b/src/test/ui/generic-associated-types/issue-78671.base.stderr new file mode 100644 index 000000000..6bcd004b1 --- /dev/null +++ b/src/test/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:11: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:8: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:11: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:8: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/src/test/ui/generic-associated-types/issue-78671.extended.stderr b/src/test/ui/generic-associated-types/issue-78671.extended.stderr new file mode 100644 index 000000000..f1b489335 --- /dev/null +++ b/src/test/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:11: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:8: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/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs new file mode 100644 index 000000000..c09dac28b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78671.rs @@ -0,0 +1,18 @@ +// revisions: base extended + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-79422.base.stderr b/src/test/ui/generic-associated-types/issue-79422.base.stderr new file mode 100644 index 000000000..404c975d6 --- /dev/null +++ b/src/test/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:48: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:24: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:48: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:24: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:45: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:24: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 because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>` + = 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/src/test/ui/generic-associated-types/issue-79422.extended.stderr b/src/test/ui/generic-associated-types/issue-79422.extended.stderr new file mode 100644 index 000000000..9bcbd7471 --- /dev/null +++ b/src/test/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:48: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:24: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:45: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:29: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/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs new file mode 100644 index 000000000..7749975e6 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -0,0 +1,51 @@ +// revisions: base extended + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-79636-1.rs b/src/test/ui/generic-associated-types/issue-79636-1.rs new file mode 100644 index 000000000..6d73fd68d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-1.rs @@ -0,0 +1,23 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr new file mode 100644 index 000000000..1ecb86282 --- /dev/null +++ b/src/test/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:15: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:5: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/src/test/ui/generic-associated-types/issue-79636-2.rs b/src/test/ui/generic-associated-types/issue-79636-2.rs new file mode 100644 index 000000000..cdaf2e483 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-2.rs @@ -0,0 +1,17 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr new file mode 100644 index 000000000..ae61b7b10 --- /dev/null +++ b/src/test/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:11: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:4: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/src/test/ui/generic-associated-types/issue-80433-reduced.rs b/src/test/ui/generic-associated-types/issue-80433-reduced.rs new file mode 100644 index 000000000..f15d4d8b1 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433-reduced.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-80433.rs b/src/test/ui/generic-associated-types/issue-80433.rs new file mode 100644 index 000000000..6a1fe7519 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433.rs @@ -0,0 +1,34 @@ +#![feature(generic_associated_types)] + +#[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/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr new file mode 100644 index 000000000..d8c210dcf --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `TestMut::Output` + --> $DIR/issue-80433.rs:23: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:9: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/src/test/ui/generic-associated-types/issue-81487.rs b/src/test/ui/generic-associated-types/issue-81487.rs new file mode 100644 index 000000000..7f399c4f9 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-81487.rs @@ -0,0 +1,19 @@ +// build-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs new file mode 100644 index 000000000..fa2f86242 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs @@ -0,0 +1,20 @@ +// Regression test for #81712. + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr new file mode 100644 index 000000000..86c99c32f --- /dev/null +++ b/src/test/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:16: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:13: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/src/test/ui/generic-associated-types/issue-81862.rs b/src/test/ui/generic-associated-types/issue-81862.rs new file mode 100644 index 000000000..e457bca0c --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-81862.rs @@ -0,0 +1,12 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr new file mode 100644 index 000000000..c664b3ee6 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-81862.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `StreamingIterator::Item` + --> $DIR/issue-81862.rs:5: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:4:10 + | +LL | type Item<'a>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn next(&mut self) -> Option<Self::Item<'a>>; + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-84931.rs b/src/test/ui/generic-associated-types/issue-84931.rs new file mode 100644 index 000000000..9e247de16 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-84931.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] +// 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/src/test/ui/generic-associated-types/issue-84931.stderr b/src/test/ui/generic-associated-types/issue-84931.stderr new file mode 100644 index 000000000..11c3dffde --- /dev/null +++ b/src/test/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:15: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/src/test/ui/generic-associated-types/issue-85921.rs b/src/test/ui/generic-associated-types/issue-85921.rs new file mode 100644 index 000000000..df59f497d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-85921.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-86483.rs b/src/test/ui/generic-associated-types/issue-86483.rs new file mode 100644 index 000000000..07dd0bffd --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86483.rs @@ -0,0 +1,16 @@ +// Regression test of #86483. +// +// Made to pass as part of fixing #98095. +// +// check-pass + +#![feature(generic_associated_types)] + +pub trait IceIce<T> +where + for<'a> T: 'a, +{ + type Ice<'v>: IntoIterator<Item = &'v T>; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs new file mode 100644 index 000000000..0f8096c8a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86787.rs @@ -0,0 +1,38 @@ +#![feature(generic_associated_types)] +// 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/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr new file mode 100644 index 000000000..d4b2267d3 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86787.stderr @@ -0,0 +1,13 @@ +error: missing required bound on `TRef` + --> $DIR/issue-86787.rs:11: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/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs new file mode 100644 index 000000000..c65f3fb2a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr new file mode 100644 index 000000000..db3a5c819 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_a.rs:18:26 + | +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ + | + = note: `FooFuture` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs new file mode 100644 index 000000000..f59e0d766 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr new file mode 100644 index 000000000..9faccc961 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_b.rs:17: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/src/test/ui/generic-associated-types/issue-87429-2.rs b/src/test/ui/generic-associated-types/issue-87429-2.rs new file mode 100644 index 000000000..d35bb098a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87429-2.rs @@ -0,0 +1,20 @@ +// 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 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs new file mode 100644 index 000000000..9ee07c2f1 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs @@ -0,0 +1,18 @@ +// check-fail + +#![feature(associated_type_defaults)] +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr new file mode 100644 index 000000000..c6fa02cb9 --- /dev/null +++ b/src/test/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:14: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:14: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/src/test/ui/generic-associated-types/issue-87429-specialization.rs b/src/test/ui/generic-associated-types/issue-87429-specialization.rs new file mode 100644 index 000000000..b365e07fe --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87429-specialization.rs @@ -0,0 +1,25 @@ +// check-fail + +#![feature(specialization)] +//~^ WARN incomplete +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr new file mode 100644 index 000000000..015e0c779 --- /dev/null +++ b/src/test/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: `#[warn(incomplete_features)]` on by default + = 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 + +error[E0277]: can't compare `Foo` with `Foo` + --> $DIR/issue-87429-specialization.rs:21: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:8: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/src/test/ui/generic-associated-types/issue-87429.rs b/src/test/ui/generic-associated-types/issue-87429.rs new file mode 100644 index 000000000..f905348ae --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87429.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-87750.rs b/src/test/ui/generic-associated-types/issue-87750.rs new file mode 100644 index 000000000..89bd79ac2 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87750.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] + +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>>; + //~^ ERROR overflow evaluating the requirement `Node<i32, RcFamily>: Sized` +} diff --git a/src/test/ui/generic-associated-types/issue-87750.stderr b/src/test/ui/generic-associated-types/issue-87750.stderr new file mode 100644 index 000000000..854541f3d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87750.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `Node<i32, RcFamily>: Sized` + --> $DIR/issue-87750.rs:20:16 + | +LL | let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs new file mode 100644 index 000000000..4952a0825 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88287.rs @@ -0,0 +1,40 @@ +// edition:2018 + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-88287.stderr b/src/test/ui/generic-associated-types/issue-88287.stderr new file mode 100644 index 000000000..5241d85a5 --- /dev/null +++ b/src/test/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:35: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:25: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/src/test/ui/generic-associated-types/issue-88360.rs b/src/test/ui/generic-associated-types/issue-88360.rs new file mode 100644 index 000000000..8ee98201a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88360.rs @@ -0,0 +1,20 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-88360.stderr b/src/test/ui/generic-associated-types/issue-88360.stderr new file mode 100644 index 000000000..5f769d799 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88360.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-88360.rs:15: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/src/test/ui/generic-associated-types/issue-88405.rs b/src/test/ui/generic-associated-types/issue-88405.rs new file mode 100644 index 000000000..4a405bd36 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88405.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs new file mode 100644 index 000000000..3b26a1801 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88459.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs new file mode 100644 index 000000000..e0796dfec --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr new file mode 100644 index 000000000..79d3479af --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -0,0 +1,16 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-88595.rs:21:35 + | +LL | fn a(&'a self) -> Self::B<'a> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/issue-88595.rs:18:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +LL | type B<'b> = impl Clone; + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/issue-89352.rs b/src/test/ui/generic-associated-types/issue-89352.rs new file mode 100644 index 000000000..d9c656d5f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-89352.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs new file mode 100644 index 000000000..f110b0693 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90014.rs @@ -0,0 +1,22 @@ +// edition:2018 + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr new file mode 100644 index 000000000..457c582e8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -0,0 +1,18 @@ +error[E0477]: the type `&mut ()` does not fulfill the required lifetime + --> $DIR/issue-90014.rs:14:20 + | +LL | type Fut<'a> where Self: 'a; + | ------------ definition of `Fut` from trait +... +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-90014.rs:14:14 + | +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/issue-90729.rs b/src/test/ui/generic-associated-types/issue-90729.rs new file mode 100644 index 000000000..98295cce8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90729.rs @@ -0,0 +1,38 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-91139.migrate.stderr b/src/test/ui/generic-associated-types/issue-91139.migrate.stderr new file mode 100644 index 000000000..b424d9a2f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91139.migrate.stderr @@ -0,0 +1,13 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-91139.rs:27:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo<T: 'a>() { + | ++++ + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs new file mode 100644 index 000000000..40eef11f0 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -0,0 +1,36 @@ +#![feature(generic_associated_types)] + +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 + //~| ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + //~| ERROR `T` may 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/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr new file mode 100644 index 000000000..b789b3a42 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91139.stderr @@ -0,0 +1,62 @@ +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:12 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo<T: 'static>() { + | +++++++++ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/generic-associated-types/issue-91762.rs b/src/test/ui/generic-associated-types/issue-91762.rs new file mode 100644 index 000000000..b259a3c6e --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.rs @@ -0,0 +1,30 @@ +// check-fail + +// FIXME(generic_associated_types): We almost certaintly 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. + +#![feature(generic_associated_types)] + +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); + //~^ type annotations needed + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-91762.stderr b/src/test/ui/generic-associated-types/issue-91762.stderr new file mode 100644 index 000000000..c2785fee3 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-91762.rs:25: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/src/test/ui/generic-associated-types/issue-91883.rs b/src/test/ui/generic-associated-types/issue-91883.rs new file mode 100644 index 000000000..3d4585a44 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91883.rs @@ -0,0 +1,42 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-91883.stderr b/src/test/ui/generic-associated-types/issue-91883.stderr new file mode 100644 index 000000000..baf4889cc --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91883.stderr @@ -0,0 +1,23 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-91883.rs:32:24 + | +LL | type Cursor<'tx>: Cursor<'tx> + | ----------------------------- definition of `Cursor` from trait +... +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` + | +note: lifetime parameter instantiated with the lifetime `'db` as defined here + --> $DIR/issue-91883.rs:31: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:32:17 + | +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/issue-92033.rs b/src/test/ui/generic-associated-types/issue-92033.rs new file mode 100644 index 000000000..1d5f7d5c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92033.rs @@ -0,0 +1,39 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr new file mode 100644 index 000000000..6dd901027 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -0,0 +1,18 @@ +error[E0477]: the type `&'s Texture` does not fulfill the required lifetime + --> $DIR/issue-92033.rs:22:28 + | +LL | type TextureIter<'a>: Iterator<Item = &'a Texture> + | -------------------------------------------------- definition of `TextureIter` from trait +... +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-92033.rs:22:22 + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr new file mode 100644 index 000000000..c74161cd3 --- /dev/null +++ b/src/test/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:20: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:20: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/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs new file mode 100644 index 000000000..377b8164a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -0,0 +1,30 @@ +// edition:2018 + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-92096.stderr b/src/test/ui/generic-associated-types/issue-92096.stderr new file mode 100644 index 000000000..ca61a0f43 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.stderr @@ -0,0 +1,8 @@ +error: `C` does not live long enough + --> $DIR/issue-92096.rs:19:5 + | +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/issue-92280.rs b/src/test/ui/generic-associated-types/issue-92280.rs new file mode 100644 index 000000000..81d000f10 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92280.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-92954.rs b/src/test/ui/generic-associated-types/issue-92954.rs new file mode 100644 index 000000000..95c090ff4 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92954.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(generic_associated_types)] + +pub trait Foo { + type Assoc<'c>; + fn function() -> for<'x> fn(Self::Assoc<'x>); +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-93141.rs b/src/test/ui/generic-associated-types/issue-93141.rs new file mode 100644 index 000000000..39ca77d13 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93141.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-93262.rs b/src/test/ui/generic-associated-types/issue-93262.rs new file mode 100644 index 000000000..adc6aa8fa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93262.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-93340.rs b/src/test/ui/generic-associated-types/issue-93340.rs new file mode 100644 index 000000000..d065bde88 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93340.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-93341.rs b/src/test/ui/generic-associated-types/issue-93341.rs new file mode 100644 index 000000000..e96a768ec --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93341.rs @@ -0,0 +1,55 @@ +// check-pass + +#![feature(generic_associated_types)] +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/src/test/ui/generic-associated-types/issue-93342.rs b/src/test/ui/generic-associated-types/issue-93342.rs new file mode 100644 index 000000000..d8d7adac9 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93342.rs @@ -0,0 +1,57 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-93874.rs b/src/test/ui/generic-associated-types/issue-93874.rs new file mode 100644 index 000000000..f403d7516 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93874.rs @@ -0,0 +1,35 @@ +// check-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/issue-95305.rs b/src/test/ui/generic-associated-types/issue-95305.rs new file mode 100644 index 000000000..e2f1710fa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-95305.rs @@ -0,0 +1,20 @@ +// 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(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/issue-95305.stderr b/src/test/ui/generic-associated-types/issue-95305.stderr new file mode 100644 index 000000000..d8557525f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-95305.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-95305.rs:11: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/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs new file mode 100644 index 000000000..af0049891 --- /dev/null +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -0,0 +1,46 @@ +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs new file mode 100644 index 000000000..655abd18d --- /dev/null +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -0,0 +1,35 @@ +// Test that the predicate printed in an unresolved method error prints the +// generics for a generic associated type. + +#![feature(generic_associated_types)] + +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 unsatisfied trait bound introduced here +//~| 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/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr new file mode 100644 index 000000000..d9dc77ac8 --- /dev/null +++ b/src/test/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:30: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:14: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/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed new file mode 100644 index 000000000..2315810a4 --- /dev/null +++ b/src/test/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/src/test/ui/generic-associated-types/missing-bounds.rs b/src/test/ui/generic-associated-types/missing-bounds.rs new file mode 100644 index 000000000..ffafff5e9 --- /dev/null +++ b/src/test/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/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr new file mode 100644 index 000000000..138c642dd --- /dev/null +++ b/src/test/ui/generic-associated-types/missing-bounds.stderr @@ -0,0 +1,98 @@ +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` +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/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs new file mode 100644 index 000000000..8171dc0ae --- /dev/null +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -0,0 +1,13 @@ +// check-fail + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr new file mode 100644 index 000000000..edd1f9367 --- /dev/null +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/missing-where-clause-on-trait.rs:9: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` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.rs b/src/test/ui/generic-associated-types/missing_lifetime_args.rs new file mode 100644 index 000000000..cd918157f --- /dev/null +++ b/src/test/ui/generic-associated-types/missing_lifetime_args.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr new file mode 100644 index 000000000..7cf3f4b73 --- /dev/null +++ b/src/test/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:13: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:4:10 + | +LL | type Y<'a, 'b>; + | ^ -- -- +help: add missing lifetime arguments + | +LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {} + | ~~~~~~~~~ + +error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/missing_lifetime_args.rs:16: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:7: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:19: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:7:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime arguments + | +LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {} + | ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/missing_lifetime_const.rs b/src/test/ui/generic-associated-types/missing_lifetime_const.rs new file mode 100644 index 000000000..e3e78dd96 --- /dev/null +++ b/src/test/ui/generic-associated-types/missing_lifetime_const.rs @@ -0,0 +1,12 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/missing_lifetime_const.stderr b/src/test/ui/generic-associated-types/missing_lifetime_const.stderr new file mode 100644 index 000000000..5d50637bd --- /dev/null +++ b/src/test/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:8: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:4: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/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs new file mode 100644 index 000000000..0508cc2da --- /dev/null +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs @@ -0,0 +1,19 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr new file mode 100644 index 000000000..53d76fd22 --- /dev/null +++ b/src/test/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:12: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:9: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:12: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:9: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:15: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:9: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/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs new file mode 100644 index 000000000..6ca0bc6dd --- /dev/null +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -0,0 +1,34 @@ +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr new file mode 100644 index 000000000..1458bf0c4 --- /dev/null +++ b/src/test/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:15: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:17: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:19: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:26: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:28: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:30: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/src/test/ui/generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/generic-associated-types/parse/in-trait-impl.rs new file mode 100644 index 000000000..7f4775ddb --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/in-trait-impl.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Z parse-only + +#![feature(generic_associated_types)] + +impl<T> Baz for T where T: Foo { + type Quux<'a> = <T as Foo>::Bar<'a, 'static>; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/parse/in-trait.rs b/src/test/ui/generic-associated-types/parse/in-trait.rs new file mode 100644 index 000000000..d438795eb --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/in-trait.rs @@ -0,0 +1,24 @@ +// check-pass +// compile-flags: -Z parse-only + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs new file mode 100644 index 000000000..be85598b7 --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs @@ -0,0 +1,10 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr new file mode 100644 index 000000000..2b265e921 --- /dev/null +++ b/src/test/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:7: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/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs new file mode 100644 index 000000000..d57c2813b --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr new file mode 100644 index 000000000..272afc10b --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -0,0 +1,23 @@ +error: expected expression, found `)` + --> $DIR/trait-path-expressions.rs:8: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:18: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/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs new file mode 100644 index 000000000..791486480 --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -0,0 +1,20 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr new file mode 100644 index 000000000..3ace774a0 --- /dev/null +++ b/src/test/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:8: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:8: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:8: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:16: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:8: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/src/test/ui/generic-associated-types/parse/trait-path-segments.rs b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs new file mode 100644 index 000000000..e943f075f --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs @@ -0,0 +1,34 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr new file mode 100644 index 000000000..7394393c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -0,0 +1,41 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:8: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:19: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:30: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/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs new file mode 100644 index 000000000..4846af96d --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -0,0 +1,13 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr new file mode 100644 index 000000000..46ddcb635 --- /dev/null +++ b/src/test/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:8: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:4:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg : Box<dyn X<Y<'a, 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:8: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:4: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/src/test/ui/generic-associated-types/parse/trait-path-types.rs b/src/test/ui/generic-associated-types/parse/trait-path-types.rs new file mode 100644 index 000000000..856253cc7 --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr new file mode 100644 index 000000000..fe9ed579e --- /dev/null +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr @@ -0,0 +1,41 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:8: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:13: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:18: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/src/test/ui/generic-associated-types/pointer_family.rs b/src/test/ui/generic-associated-types/pointer_family.rs new file mode 100644 index 000000000..da86e7f27 --- /dev/null +++ b/src/test/ui/generic-associated-types/pointer_family.rs @@ -0,0 +1,36 @@ +#![feature(generic_associated_types)] + +// 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/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs new file mode 100644 index 000000000..794d677c8 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -0,0 +1,61 @@ +// Like `projection-bound-cycle.rs` but this avoids using +// `feature(trivial_bounds)`. + +#![feature(generic_associated_types)] + +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; +} + +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>; + //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized` +} + +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/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr new file mode 100644 index 000000000..2b57c439f --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized` + --> $DIR/projection-bound-cycle-generic.rs:44:18 + | +LL | type Assoc = OnlySized<<T as Foo>::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `OnlySized` + --> $DIR/projection-bound-cycle-generic.rs:28:18 + | +LL | struct OnlySized<T> where T: Sized { f: T } + | ^ required by this bound in `OnlySized` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs new file mode 100644 index 000000000..6564a3608 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -0,0 +1,63 @@ +// 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(generic_associated_types)] +#![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; +} + +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>; + //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized` +} + +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/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr new file mode 100644 index 000000000..d9d0bf427 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized` + --> $DIR/projection-bound-cycle.rs:46:18 + | +LL | type Assoc = OnlySized<<T as Foo>::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `OnlySized` + --> $DIR/projection-bound-cycle.rs:30:18 + | +LL | struct OnlySized<T> where T: Sized { f: T } + | ^ required by this bound in `OnlySized` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs new file mode 100644 index 000000000..a40c0c2c4 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs @@ -0,0 +1,35 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr new file mode 100644 index 000000000..4620aa34e --- /dev/null +++ b/src/test/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:17: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:22: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:27: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/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs new file mode 100644 index 000000000..300907adb --- /dev/null +++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs @@ -0,0 +1,213 @@ +#![feature(generic_associated_types)] + +// 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>); +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr new file mode 100644 index 000000000..fdb1f50a7 --- /dev/null +++ b/src/test/ui/generic-associated-types/self-outlives-lint.stderr @@ -0,0 +1,167 @@ +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:9: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:25: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:39: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:46: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:61: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:77: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:92: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:114: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:122: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:129: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 `Item` + --> $DIR/self-outlives-lint.rs:142: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 `Iterator` + --> $DIR/self-outlives-lint.rs:144: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:150: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:159: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:175: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: aborting due to 15 previous errors + diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs new file mode 100644 index 000000000..2a9763457 --- /dev/null +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -0,0 +1,31 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr new file mode 100644 index 000000000..be7659209 --- /dev/null +++ b/src/test/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:4: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:13: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:18: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:27: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/src/test/ui/generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs new file mode 100644 index 000000000..e71b6805a --- /dev/null +++ b/src/test/ui/generic-associated-types/streaming_iterator.rs @@ -0,0 +1,76 @@ +// run-pass + +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/trait-objects.base.stderr b/src/test/ui/generic-associated-types/trait-objects.base.stderr new file mode 100644 index 000000000..1df76a21b --- /dev/null +++ b/src/test/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:14: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:8: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/src/test/ui/generic-associated-types/trait-objects.extended.stderr b/src/test/ui/generic-associated-types/trait-objects.extended.stderr new file mode 100644 index 000000000..52d48d578 --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.extended.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/trait-objects.rs:16: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` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs new file mode 100644 index 000000000..c1da1e0a3 --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.rs @@ -0,0 +1,20 @@ +// revisions: base extended + +#![feature(generic_associated_types)] +#![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/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs new file mode 100644 index 000000000..8b40dac57 --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs @@ -0,0 +1,27 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr new file mode 100644 index 000000000..ae52010cc --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr @@ -0,0 +1,50 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/unsatified-item-lifetime-bound.rs:4: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:13: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:12: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:18: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:17: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:23:8 + | +LL | f: <() as X>::Y<'a>, + | ^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:22: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/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs new file mode 100644 index 000000000..6466bf98d --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -0,0 +1,21 @@ +#![feature(generic_associated_types)] + +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/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr new file mode 100644 index 000000000..7ec9386ca --- /dev/null +++ b/src/test/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:8: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:8:15 + | +LL | type Item<'a> = &'b (); + | ^^ + +error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:17:21 + | +LL | type Item<'a> = &'a (); + | ^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/unsatisfied-outlives-bound.rs:13: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/src/test/ui/generic-associated-types/variance_constraints.rs b/src/test/ui/generic-associated-types/variance_constraints.rs new file mode 100644 index 000000000..7d0f7638a --- /dev/null +++ b/src/test/ui/generic-associated-types/variance_constraints.rs @@ -0,0 +1,23 @@ +// check-pass +// issue #69184 +#![feature(generic_associated_types)] + +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() {} |