1 // check-pass
2
3 // FamilyType (GAT workaround)
4 pub trait FamilyLt<'a> {
5 type Out;
6 }
7
8 struct RefMutFamily<T>(std::marker::PhantomData<T>, ());
9 impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily<T> {
10 type Out = &'a mut T;
11 }
12
13 pub trait Execute {
14 type E: Inject;
execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out)15 fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out);
16 }
17
18 pub trait Inject
19 where
20 Self: Sized,
21 {
22 type I: for<'a> FamilyLt<'a>;
inject(_: &()) -> <Self::I as FamilyLt>::Out23 fn inject(_: &()) -> <Self::I as FamilyLt>::Out;
24 }
25
26 impl<T: 'static> Inject for RefMutFamily<T> {
27 type I = Self;
inject(_: &()) -> <Self::I as FamilyLt>::Out28 fn inject(_: &()) -> <Self::I as FamilyLt>::Out {
29 unimplemented!()
30 }
31 }
32
33 // This struct is only used to give a hint to the compiler about the type `Q`
34 struct Annotate<Q>(std::marker::PhantomData<Q>);
35 impl<Q> Annotate<Q> {
new() -> Self36 fn new() -> Self {
37 Self(std::marker::PhantomData)
38 }
39 }
40
41 // This function annotate a closure so it can have Higher-Rank Lifetime Bounds
42 //
43 // See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052
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,44 fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
45 where
46 F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
47 Q: Inject + 'static,
48 {
49 let wrapper: Wrapper<Q, F> = Wrapper(std::marker::PhantomData, func);
50 wrapper
51 }
52
53 struct Wrapper<Q, F>(std::marker::PhantomData<Q>, F);
54 impl<Q, F> Execute for Wrapper<Q, F>
55 where
56 Q: Inject,
57 F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out),
58 {
59 type E = Q;
60
execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out)61 fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out) {
62 (self.1)(value)
63 }
64 }
65
66 struct Task {
67 _processor: Box<dyn FnOnce()>,
68 }
69
70 // This function consume the closure
task<P>(processor: P) -> Task where P: Execute + 'static71 fn task<P>(processor: P) -> Task
72 where P: Execute + 'static {
73 Task {
74 _processor: Box::new(move || {
75 let q = P::E::inject(&());
76 processor.execute(q);
77 })
78 }
79 }
80
main()81 fn main() {
82 task(annotate(
83 Annotate::<RefMutFamily<usize>>::new(),
84 |value: &mut usize| {
85 *value = 2;
86 }
87 ));
88 }
89