1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2019 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/

use crate::utils::tuple::ElementSatisfy;

/// This trait is designed for associated type in trait, such as iterator,
/// where the type could be a borrow of self, or an independent type.
///
/// It's difficult to offer generic trait methods implementation for all
/// variants. One possible way is to use HRTB, however under some cases we
/// could only implement '_ or have implementation for '_ instead of
/// for<'any>, especially when we have no control over third-party code,
/// which render some usages infeasible.
///
/// Say if we have the code below:
/// ```
/// trait LifetimeBoundedTrait<'a> {
///     fn get(&'a mut self) -> T<'a>;
/// }
///
/// #[derive(Debug)]
/// struct T<'a> {
///     s: &'a i64,
/// }
///
/// struct EndUserType<TypeImplTrait> {
///     v: TypeImplTrait,
/// }
///
/// impl<T> EndUserType<T>
/// where for<'a> T: LifetimeBoundedTrait<'a>
/// {
///     fn use_t(&mut self) {
///         let ret = self.v.get();
///         println!("{:?}", ret);
///     }
/// }
///
/// struct ConcreteType {}
///
/// impl<'a> LifetimeBoundedTrait<'a> for ConcreteType {
///     fn get(&'a mut self) -> T<'a> { T { s: &0 } }
/// }
///
/// impl<'a: 'b, 'b> LifetimeBoundedTrait<'b> for &'a mut ConcreteType {
///     fn get(&'b mut self) -> T<'b> { (*self).get() }
/// }
/// ```
///
/// Ideally, we could store &mut ConcreteType in EndUserType#use_t in the
/// same way. But It's not possible for the EndUserType to store &mut
/// ConcreteType as v, because &mut ConcreteType only implements
/// LifetimeBoundedTrait for '_, not for any lifetime.
///
/// What we have to do, is to drop the lifetime bound for 'a, which is
/// counter-intuitive but works.
///
/// impl<'a, 'b> LifetimeBoundedTrait<'b> for &'a mut ConcreteType {
///     fn get(&'b mut self) -> T<'b> { (*self).get() }
/// }
///
/// In some other cases, with &'x F, rust requires F: 'x in generic type
/// constrain, which may be harder to workaround for HRTB.

pub trait WrappedLifetimeFamily<'a, Constrain: ?Sized> {
    type Out: 'a + Sized + ElementSatisfy<Constrain>;
}

pub trait WrappedTrait<Constrain: ?Sized>:
    for<'a> WrappedLifetimeFamily<'a, Constrain>
{
}

pub struct Wrap<
    'a,
    Wrapped: ?Sized + WrappedTrait<Constrain>,
    Constrain: ?Sized,
>(pub <Wrapped as WrappedLifetimeFamily<'a, Constrain>>::Out);

impl<'a, Wrapped: ?Sized + WrappedTrait<Constrain>, Constrain: ?Sized>
    Wrap<'a, Wrapped, Constrain>
{
    pub fn take(
        self,
    ) -> <Wrapped as WrappedLifetimeFamily<'a, Constrain>>::Out {
        self.0
    }
}