• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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