diff options
Diffstat (limited to '')
-rw-r--r-- | src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs new file mode 100644 index 000000000..c6f29fa59 --- /dev/null +++ b/src/test/ui/higher-rank-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; + } + )); +} |