diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /tests/ui/higher-ranked/trait-bounds/normalize-under-binder | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/higher-ranked/trait-bounds/normalize-under-binder')
30 files changed, 1185 insertions, 0 deletions
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs new file mode 100644 index 000000000..f255eac0c --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait Foo<'a> { + type Bar; + fn foo(&'a self) -> Self::Bar; +} + +impl<'a, 'b, T: 'a> Foo<'a> for &'b T { + type Bar = &'a T; + fn foo(&'a self) -> &'a T { + self + } +} + +pub fn uncallable<T, F>(x: T, f: F) +where + T: for<'a> Foo<'a>, + F: for<'a> Fn(<T as Foo<'a>>::Bar), +{ + f(x.foo()); +} + +pub fn catalyst(x: &i32) { + broken(x, |_| {}) +} + +pub fn broken<F: Fn(&i32)>(x: &i32, f: F) { + uncallable(x, |y| f(y)); +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs new file mode 100644 index 000000000..4d38cb19e --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs @@ -0,0 +1,30 @@ +// check-pass + +fn foo<T>(t: T) -> usize +where + for<'a> &'a T: IntoIterator, + for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator, +{ + t.into_iter().len() +} + +fn main() { + foo::<Vec<u32>>(vec![]); +} + +mod another { + use std::ops::Deref; + + fn test<T, TDeref>() + where + T: Deref<Target = TDeref>, + TDeref: ?Sized, + for<'a> &'a TDeref: IntoIterator, + for<'a> <&'a TDeref as IntoIterator>::IntoIter: Clone, + { + } + + fn main() { + test::<Vec<u8>, _>(); + } +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs new file mode 100644 index 000000000..c6f29fa59 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -0,0 +1,88 @@ +// check-pass + +// FamilyType (GAT workaround) +pub trait FamilyLt<'a> { + type Out; +} + +struct RefMutFamily<T>(std::marker::PhantomData<T>, ()); +impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily<T> { + type Out = &'a mut T; +} + +pub trait Execute { + type E: Inject; + fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out); +} + +pub trait Inject +where + Self: Sized, +{ + type I: for<'a> FamilyLt<'a>; + fn inject(_: &()) -> <Self::I as FamilyLt>::Out; +} + +impl<T: 'static> Inject for RefMutFamily<T> { + type I = Self; + fn inject(_: &()) -> <Self::I as FamilyLt>::Out { + unimplemented!() + } +} + +// This struct is only used to give a hint to the compiler about the type `Q` +struct Annotate<Q>(std::marker::PhantomData<Q>); +impl<Q> Annotate<Q> { + fn new() -> Self { + Self(std::marker::PhantomData) + } +} + +// This function annotate a closure so it can have Higher-Rank Lifetime Bounds +// +// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052 +fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static +where + F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static, + Q: Inject + 'static, +{ + let wrapper: Wrapper<Q, F> = Wrapper(std::marker::PhantomData, func); + wrapper +} + +struct Wrapper<Q, F>(std::marker::PhantomData<Q>, F); +impl<Q, F> Execute for Wrapper<Q, F> + where + Q: Inject, + F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out), +{ + type E = Q; + + fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out) { + (self.1)(value) + } +} + +struct Task { + _processor: Box<dyn FnOnce()>, +} + +// This function consume the closure +fn task<P>(processor: P) -> Task +where P: Execute + 'static { + Task { + _processor: Box::new(move || { + let q = P::E::inject(&()); + processor.execute(q); + }) + } +} + +fn main() { + task(annotate( + Annotate::<RefMutFamily<usize>>::new(), + |value: &mut usize| { + *value = 2; + } + )); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs new file mode 100644 index 000000000..002054732 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs @@ -0,0 +1,33 @@ +// check-pass + +use std::marker::PhantomData; + +trait Lt<'a> { + type T; +} +struct Id<T>(PhantomData<T>); +impl<'a,T> Lt<'a> for Id<T> { + type T = T; +} + +struct Ref<T>(PhantomData<T>) where T: ?Sized; +impl<'a,T> Lt<'a> for Ref<T> +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a T; +} +struct Mut<T>(PhantomData<T>) where T: ?Sized; +impl<'a,T> Lt<'a> for Mut<T> +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a mut T; +} + +struct C<I,O>(for<'a> fn(<I as Lt<'a>>::T) -> O) where I: for<'a> Lt<'a>; + + +fn main() { + let c = C::<Id<_>,_>(|()| 3); + c.0(()); + +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs new file mode 100644 index 000000000..d84e30f49 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -0,0 +1,32 @@ +trait ATC<'a> { + type Type: Sized; +} + +trait WithDefault: for<'a> ATC<'a> { + fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F); +} + +fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>( + f: F, + x: <T as ATC<'b>>::Type, +) { + f(x); +} + +impl<'a> ATC<'a> for () { + type Type = Self; +} + +impl WithDefault for () { + fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F) { + // Errors with a bogus type mismatch. + //f(()); + // Going through another generic function works fine. + call(f, ()); + //~^ expected a + } +} + +fn main() { + // <()>::with_default(|_| {}); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr new file mode 100644 index 000000000..b30dd36d2 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + --> $DIR/issue-62529-3.rs:25:14 + | +LL | call(f, ()); + | ---- ^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `((),)` + found a closure with arguments `(<_ as ATC<'a>>::Type,)` +note: required by a bound in `call` + --> $DIR/issue-62529-3.rs:9:36 + | +LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs new file mode 100644 index 000000000..8c2a59868 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs @@ -0,0 +1,39 @@ +// check-pass + +use std::marker::PhantomData; +use std::mem; + +trait Container<'a> { + type Root: 'a; +} + +type RootOf<'a, T> = <T as Container<'a>>::Root; + +struct Test<'a, T> where T: Container<'a> { + pub root: T::Root, + marker: PhantomData<&'a mut &'a mut ()>, +} + +impl<'a, 'b> Container<'b> for &'a str { + type Root = &'b str; +} + +impl<'a, T> Test<'a, T> where T: for<'b> Container<'b> { + fn new(root: RootOf<'a, T>) -> Test<'a, T> { + Test { + root: root, + marker: PhantomData + } + } + + fn with_mut<F, R>(&mut self, f: F) -> R where + F: for<'b> FnOnce(&'b mut RootOf<'b, T>) -> R { + f(unsafe { mem::transmute(&mut self.root) }) + } +} + +fn main() { + let val = "root"; + let mut test: Test<&str> = Test::new(val); + test.with_mut(|_| { }); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs new file mode 100644 index 000000000..03f257a02 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs @@ -0,0 +1,27 @@ +// check-pass + +pub struct Struct {} + +pub trait Trait<'a> { + type Assoc; + + fn method() -> Self::Assoc; +} + +impl<'a> Trait<'a> for Struct { + type Assoc = (); + + fn method() -> Self::Assoc {} +} + +pub fn function<F, T>(f: F) +where + F: for<'a> FnOnce(<T as Trait<'a>>::Assoc), + T: for<'b> Trait<'b>, +{ + f(T::method()); +} + +fn main() { + function::<_, Struct>(|_| {}); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs new file mode 100644 index 000000000..0ea736dee --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs @@ -0,0 +1,77 @@ +// check-pass + +use std::cell::RefMut; + +fn main() { + StateMachine2::Init.resume(); +} + +enum StateMachine2<'a> { + Init, + #[allow(dead_code)] // match required for ICE + AfterTwoYields { + p: Backed<'a, *mut String>, + }, +} + +impl<'a> StateMachine2<'a> { + fn take(&self) -> Self { + StateMachine2::Init + } +} + +impl<'a> StateMachine2<'a> { + fn resume(&mut self) -> () { + use StateMachine2::*; + match self.take() { + AfterTwoYields { p } => { + p.with(|_| {}); + } + _ => panic!("Resume after completed."), + } + } +} + +unsafe trait Unpack<'a> { + type Unpacked: 'a; + + fn unpack(&self) -> Self::Unpacked { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe trait Pack { + type Packed; + + fn pack(&self) -> Self::Packed { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe impl<'a> Unpack<'a> for String { + type Unpacked = String; +} + +unsafe impl Pack for String { + type Packed = String; +} + +unsafe impl<'a> Unpack<'a> for *mut String { + type Unpacked = &'a mut String; +} + +unsafe impl<'a> Pack for &'a mut String { + type Packed = *mut String; +} + +struct Backed<'a, U>(RefMut<'a, Option<String>>, U); + +impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> { + fn with<F>(self, f: F) -> Backed<'a, ()> + where + F: for<'f> FnOnce(<U as Unpack<'f>>::Unpacked) -> (), + { + let result: () = f(self.1.unpack()); + Backed(self.0, result) + } +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs new file mode 100644 index 000000000..3ced40230 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait MyTrait<'a> { + type Output: 'a; + fn gimme_value(&self) -> Self::Output; +} + +pub struct MyStruct; + +impl<'a> MyTrait<'a> for MyStruct { + type Output = &'a usize; + fn gimme_value(&self) -> Self::Output { + unimplemented!() + } +} + +fn meow<T, F>(t: T, f: F) +where + T: for<'any> MyTrait<'any>, + F: for<'any2> Fn(<T as MyTrait<'any2>>::Output), +{ + let v = t.gimme_value(); + f(v); +} + +fn main() { + let struc = MyStruct; + meow(struc, |foo| { + println!("{:?}", foo); + }) +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr new file mode 100644 index 000000000..0f38f8e32 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr @@ -0,0 +1,79 @@ +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&&str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&Wrapper<'_>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs new file mode 100644 index 000000000..1d90226a3 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs @@ -0,0 +1,51 @@ +// check-fail +#![feature(rustc_attrs)] + +trait Parser<'s> { + type Output; + + fn call(&self, input: &'s str) -> (&'s str, Self::Output); +} + +impl<'s, F, T> Parser<'s> for F +where F: Fn(&'s str) -> (&'s str, T) { + type Output = T; + fn call(&self, input: &'s str) -> (&'s str, T) { + self(input) + } +} + +fn foo<F1, F2>( + f1: F1, + base: &'static str, + f2: F2 +) +where + F1: for<'a> Parser<'a>, + F2: FnOnce(&<F1 as Parser>::Output) -> bool +{ + let s: String = base.to_owned(); + let str_ref = s.as_ref(); + let (remaining, produced) = f1.call(str_ref); + assert!(f2(&produced)); + assert_eq!(remaining.len(), 0); +} + +struct Wrapper<'a>(&'a str); + +fn main() { + fn bar<'a>(s: &'a str) -> (&'a str, &'a str) { + (&s[..1], &s[..]) + } + + fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) { + (&s[..1], Wrapper(&s[..])) + } + + foo(bar, "string", |s| s.len() == 5); + //~^ ERROR mismatched types + //~| ERROR mismatched types + foo(baz, "string", |s| s.0.len() == 5); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr new file mode 100644 index 000000000..4ef96cd95 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -0,0 +1,79 @@ +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:45:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:45:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:9 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:45:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:45:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:44 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:48:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:48:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:9 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:48:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:48:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:44 + | +LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs new file mode 100644 index 000000000..93ccb4268 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +trait A<'a> { + type B; + fn b(self) -> Self::B; +} + +struct T; +struct S<'a>(PhantomData<&'a ()>); + +impl<'a> A<'a> for T { + type B = S<'a>; + fn b(self) -> Self::B { + S(PhantomData) + } +} + +fn s<TT, F>(t: TT, f: F) +where + TT: for<'a> A<'a>, + F: for<'a> FnOnce(<TT as A<'a>>::B) +{ + f(t.b()); +} + +fn main() { + s(T, |_| {}); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs new file mode 100644 index 000000000..583470080 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs @@ -0,0 +1,15 @@ +// check-pass + +use std::ops::Deref; + +struct Data { + boxed: Box<&'static i32> +} + +impl Data { + fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target)) { + user(*self.boxed) + } +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs new file mode 100644 index 000000000..00a866f22 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs @@ -0,0 +1,71 @@ +// build-pass +// edition:2018 + +type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>; + +fn main() { + f(); +} + +async fn f() { + run("dependency").await; +} + +struct InMemoryStorage; + +struct User<'dep> { + dep: &'dep str, +} + +impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> { + fn execute(&self) -> BoxFuture<Result<(), String>> { + todo!() + } +} + +trait Storage { + type Error; +} + +impl Storage for InMemoryStorage { + type Error = String; +} + +trait StorageRequestReturnType { + type Output; +} + +trait StorageRequest<S: Storage>: StorageRequestReturnType { + fn execute( + &self, + ) -> BoxFuture<Result<<Self as StorageRequestReturnType>::Output, <S as Storage>::Error>>; +} + +struct SaveUser<'a> { + name: &'a str, +} + +impl<'a> StorageRequestReturnType for SaveUser<'a> { + type Output = (); +} + +impl<'dep> User<'dep> { + async fn save<S>(self) + where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest<S>, + { + SaveUser { name: "Joe" } + .execute() + .await; + } +} + +async fn run<S>(dep: &str) +where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest<S>, + for<'a> SaveUser<'a>: StorageRequestReturnType, +{ + User { dep }.save().await; +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs new file mode 100644 index 000000000..6316ceea1 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Bar { + type Type; +} +struct Foo<'a>(&'a ()); +impl<'a> Bar for Foo<'a> { + type Type = (); +} + +fn func<'a>(_: <Foo<'a> as Bar>::Type) {} +fn assert_is_func<A>(_: fn(A)) {} + +fn test() +where + for<'a> <Foo<'a> as Bar>::Type: Sized, +{ + assert_is_func(func); +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs new file mode 100644 index 000000000..f6ab9c203 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Indexable { + type Idx; +} +impl Indexable for u8 { + type Idx = u8; +} +impl Indexable for u16 { + type Idx = u16; +} + +pub trait Indexer<T: Indexable>: std::ops::Index<T::Idx, Output = T> {} + +trait StoreIndex: Indexer<u8> + Indexer<u16> {} + +fn foo(st: &impl StoreIndex) -> &dyn StoreIndex { + st as &dyn StoreIndex +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs new file mode 100644 index 000000000..8aa29926d --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs @@ -0,0 +1,19 @@ +#![feature(unboxed_closures)] + +trait SomeTrait<'a> { + type Associated; +} + +fn give_me_ice<T>() { + callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); + //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] + //~| ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] +} + +fn callee<T: Fn<(&'static (),)>>() { + println!("{}", std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>()); +} + +fn main() { + give_me_ice::<()>(); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr new file mode 100644 index 000000000..3240518fb --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied + --> $DIR/issue-85455.rs:8:14 + | +LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() { + | +++++++++++++++++++++++ + +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied + --> $DIR/issue-85455.rs:8:5 + | +LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() { + | +++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs new file mode 100644 index 000000000..fffb54f86 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs @@ -0,0 +1,32 @@ +trait BufferMut {} +struct Ctx<D>(D); + +trait BufferUdpStateContext<B> {} +impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} + +trait StackContext +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, +{ + type Dispatcher; +} + +trait TimerContext { + type Handler; +} +impl<C> TimerContext for C +where + C: StackContext, + //~^ ERROR: is not satisfied [E0277] +{ + type Handler = Ctx<C::Dispatcher>; + //~^ ERROR: is not satisfied [E0277] +} + +struct EthernetWorker<C>(C) +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; +impl<C> EthernetWorker<C> {} +//~^ ERROR: is not satisfied [E0277] + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr new file mode 100644 index 000000000..edef6ccd3 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr @@ -0,0 +1,69 @@ +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:19:8 + | +LL | C: StackContext, + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this trait +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:29:9 + | +LL | impl<C> EthernetWorker<C> {} + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `EthernetWorker` + --> $DIR/issue-89118.rs:28:14 + | +LL | struct EthernetWorker<C>(C) + | -------------- required by a bound in this struct +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:22:20 + | +LL | type Handler = Ctx<C::Dispatcher>; + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this trait +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs new file mode 100644 index 000000000..f7e467b37 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs @@ -0,0 +1,44 @@ +// check-pass + +#![allow(unused)] + +trait MiniYokeable<'a> { + type Output; +} + +struct MiniYoke<Y: for<'a> MiniYokeable<'a>> { + pub yokeable: Y, +} + +fn map_project_broken<Y, P>( + source: MiniYoke<Y>, + f: impl for<'a> FnOnce( + <Y as MiniYokeable<'a>>::Output, + core::marker::PhantomData<&'a ()>, + ) -> <P as MiniYokeable<'a>>::Output, +) -> MiniYoke<P> +where + Y: for<'a> MiniYokeable<'a>, + P: for<'a> MiniYokeable<'a> +{ + unimplemented!() +} + +struct Bar<'a> { + string_1: &'a str, + string_2: &'a str, +} + +impl<'a> MiniYokeable<'a> for Bar<'static> { + type Output = Bar<'a>; +} + +impl<'a> MiniYokeable<'a> for &'static str { + type Output = &'a str; +} + +fn demo_broken(bar: MiniYoke<Bar<'static>>) -> MiniYoke<&'static str> { + map_project_broken(bar, |bar, _| bar.string_1) +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs new file mode 100644 index 000000000..effc32945 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs @@ -0,0 +1,41 @@ +// check-pass + +use std::marker::PhantomData; + +trait Family: Sized { + type Item<'a>; + + fn apply_all<F>(&self, f: F) + where + F: FamilyItemFn<Self> { } +} + +struct Array<T>(PhantomData<T>); + +impl<T: 'static> Family for Array<T> { + type Item<'a> = &'a T; +} + +trait FamilyItemFn<T: Family> { + fn apply(&self, item: T::Item<'_>); +} + +impl<T, F> FamilyItemFn<T> for F +where + T: Family, + for<'a> F: Fn(T::Item<'a>) +{ + fn apply(&self, item: T::Item<'_>) { + (*self)(item); + } +} + +fn process<T: 'static>(array: Array<T>) { + // Works + array.apply_all(|x: &T| { }); + + // ICE: NoSolution + array.apply_all(|x: <Array<T> as Family>::Item<'_>| { }); +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs new file mode 100644 index 000000000..628b5cba1 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs @@ -0,0 +1,35 @@ +//check-pass + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + +trait IsCovariant<'a> {} + +struct Yoke<Y: for<'a> Yokeable<'a>> { + data: Y, +} + +impl<Y: for<'a> Yokeable<'a>> Yoke<Y> { + fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ()) + -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> { + + unimplemented!() + } +} + +fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> + { + x.project(|data, _| { + Box::new(data) + }) +} + + +impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> { + type Output = Box<dyn IsCovariant<'a> + 'a>; +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs new file mode 100644 index 000000000..ffd6857d8 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs @@ -0,0 +1,31 @@ +// check-pass + +trait Variable<'a> { + type Type; +} + +impl Variable<'_> for () { + type Type = (); +} + +fn check<F, T>(_: F) +where + F: Fn(T), // <- if removed, all fn_* then require type annotations + F: for<'a> Fn(<T as Variable<'a>>::Type), + T: for<'a> Variable<'a>, +{ +} + +fn test(arg: impl Fn(())) { + fn fn_1(_: ()) {} + let fn_2 = |_: ()| (); + let fn_3 = |a| fn_1(a); + let fn_4 = arg; + + check(fn_1); // Error + check(fn_2); // Ok + check(fn_3); // Ok + check(fn_4); // Error +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs new file mode 100644 index 000000000..ab9d9a7ce --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs @@ -0,0 +1,53 @@ +// check-fail +// known-bug: #90950 + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + + +trait IsCovariant<'a> {} + +struct Yoke<Y: for<'a> Yokeable<'a>> { + data: Y, +} + + +// impl<Y: for<'a> Yokeable<'a>> Yoke<Y> { +// fn project<Y2: for<'a> Yokeable<'a>>( +// &self, +// f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a (), +// ) -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> { +// unimplemented!() +// } +// } + +fn upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> + { + // x.project(|data, _| { + // Box::new(data) + // }) + unimplemented!() +} + + +impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> { + type Output = Box<dyn IsCovariant<'a> + 'a>; +} + +// this impl is mostly an example and unnecessary for the pure repro +use std::borrow::*; +impl<'a, T: ToOwned + ?Sized> Yokeable<'a> for Cow<'static, T> { + type Output = Cow<'a, T>; +} +impl<'a, T: ToOwned + ?Sized> IsCovariant<'a> for Cow<'a, T> {} + + + +fn upcast_yoke(y: Yoke<Cow<'static, str>>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> { + upcast(y) +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr new file mode 100644 index 000000000..5be33bccd --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `for<'a> <_ as Yokeable<'a>>::Output: IsCovariant<'a>` is not satisfied + --> $DIR/issue-90950.rs:50:12 + | +LL | upcast(y) + | ------ ^ the trait `for<'a> IsCovariant<'a>` is not implemented for `<_ as Yokeable<'a>>::Output` + | | + | required by a bound introduced by this call + | + = help: the trait `IsCovariant<'a>` is implemented for `std::borrow::Cow<'a, T>` +note: required by a bound in `upcast` + --> $DIR/issue-90950.rs:27:42 + | +LL | fn upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where + | ------ required by a bound in this function +LL | Y: for<'a> Yokeable<'a>, +LL | for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> + | ^^^^^^^^^^^^^^^ required by this bound in `upcast` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs new file mode 100644 index 000000000..7693b1182 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs @@ -0,0 +1,23 @@ +// check-fail +// known-bug: #89196 + +// Should pass, but we normalize and check bounds before we resolve the generics +// of the function (which we know because of the return type). + +trait Trait<'a> { + type Out; +} + +impl<'a, T> Trait<'a> for T { + type Out = T; +} + +fn weird_bound<X>() -> X + where + for<'a> X: Trait<'a>, + for<'a> <X as Trait<'a>>::Out: Copy +{ todo!() } + +fn main() { + let _: () = weird_bound(); +} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr new file mode 100644 index 000000000..73388a725 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satisfied + --> $DIR/norm-before-method-resolution.rs:22:17 + | +LL | let _: () = weird_bound(); + | ^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` + | +note: required by a bound in `weird_bound` + --> $DIR/norm-before-method-resolution.rs:18:40 + | +LL | fn weird_bound<X>() -> X + | ----------- required by a bound in this function +... +LL | for<'a> <X as Trait<'a>>::Out: Copy + | ^^^^ required by this bound in `weird_bound` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |