cfx_storage/utils/
wrap.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use crate::utils::tuple::ElementSatisfy;
6
7/// This trait is designed for associated type in trait, such as iterator,
8/// where the type could be a borrow of self, or an independent type.
9///
10/// It's difficult to offer generic trait methods implementation for all
11/// variants. One possible way is to use HRTB, however under some cases we
12/// could only implement '_ or have implementation for '_ instead of
13/// for<'any>, especially when we have no control over third-party code,
14/// which render some usages infeasible.
15///
16/// Say if we have the code below:
17/// ```
18/// trait LifetimeBoundedTrait<'a> {
19///     fn get(&'a mut self) -> T<'a>;
20/// }
21///
22/// #[derive(Debug)]
23/// struct T<'a> {
24///     s: &'a i64,
25/// }
26///
27/// struct EndUserType<TypeImplTrait> {
28///     v: TypeImplTrait,
29/// }
30///
31/// impl<T> EndUserType<T>
32/// where for<'a> T: LifetimeBoundedTrait<'a>
33/// {
34///     fn use_t(&mut self) {
35///         let ret = self.v.get();
36///         println!("{:?}", ret);
37///     }
38/// }
39///
40/// struct ConcreteType {}
41///
42/// impl<'a> LifetimeBoundedTrait<'a> for ConcreteType {
43///     fn get(&'a mut self) -> T<'a> { T { s: &0 } }
44/// }
45///
46/// impl<'a: 'b, 'b> LifetimeBoundedTrait<'b> for &'a mut ConcreteType {
47///     fn get(&'b mut self) -> T<'b> { (*self).get() }
48/// }
49/// ```
50///
51/// Ideally, we could store &mut ConcreteType in EndUserType#use_t in the
52/// same way. But It's not possible for the EndUserType to store &mut
53/// ConcreteType as v, because &mut ConcreteType only implements
54/// LifetimeBoundedTrait for '_, not for any lifetime.
55///
56/// What we have to do, is to drop the lifetime bound for 'a, which is
57/// counter-intuitive but works.
58///
59/// impl<'a, 'b> LifetimeBoundedTrait<'b> for &'a mut ConcreteType {
60///     fn get(&'b mut self) -> T<'b> { (*self).get() }
61/// }
62///
63/// In some other cases, with &'x F, rust requires F: 'x in generic type
64/// constrain, which may be harder to workaround for HRTB.
65
66pub trait WrappedLifetimeFamily<'a, Constrain: ?Sized> {
67    type Out: 'a + Sized + ElementSatisfy<Constrain>;
68}
69
70pub trait WrappedTrait<Constrain: ?Sized>:
71    for<'a> WrappedLifetimeFamily<'a, Constrain>
72{
73}
74
75pub struct Wrap<
76    'a,
77    Wrapped: ?Sized + WrappedTrait<Constrain>,
78    Constrain: ?Sized,
79>(pub <Wrapped as WrappedLifetimeFamily<'a, Constrain>>::Out);
80
81impl<'a, Wrapped: ?Sized + WrappedTrait<Constrain>, Constrain: ?Sized>
82    Wrap<'a, Wrapped, Constrain>
83{
84    pub fn take(
85        self,
86    ) -> <Wrapped as WrappedLifetimeFamily<'a, Constrain>>::Out {
87        self.0
88    }
89}