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
//! 用于 (作用域) 存在生命周期的 `Cell` 变体。

use std::cell::Cell;
use std::mem;
use std::ops::{Deref, DerefMut};

/// 输入具有生命周期的 lambda 应用程序。
#[allow(unused_lifetimes)]
pub trait ApplyL<'a> {
    type Out;
}

/// 获取一个有生命周期的 lambda 类型,例如 `Lifetime -> Type`。
pub trait LambdaL: for<'a> ApplyL<'a> {}

impl<T: for<'a> ApplyL<'a>> LambdaL for T {}

// HACK(eddyb) 使用 newtype 解决投影限制
// FIXME(#52812) 替换为 `&'a mut <T as ApplyL<'b>>::Out`
pub struct RefMutL<'a, 'b, T: LambdaL>(&'a mut <T as ApplyL<'b>>::Out);

impl<'a, 'b, T: LambdaL> Deref for RefMutL<'a, 'b, T> {
    type Target = <T as ApplyL<'b>>::Out;
    fn deref(&self) -> &Self::Target {
        self.0
    }
}

impl<'a, 'b, T: LambdaL> DerefMut for RefMutL<'a, 'b, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.0
    }
}

pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);

impl<T: LambdaL> ScopedCell<T> {
    pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self {
        ScopedCell(Cell::new(value))
    }

    /// 在运行 `f` 时将 `self` 中的值设置为 `replacement`,该值可变地获取旧值。
    /// `f` 退出后,即使是 panic 也将恢复旧值,包括 `f` 对其所做的修改。
    ///
    ///
    pub fn replace<'a, R>(
        &self,
        replacement: <T as ApplyL<'a>>::Out,
        f: impl for<'b, 'c> FnOnce(RefMutL<'b, 'c, T>) -> R,
    ) -> R {
        /// 即使 `f` 发生了 panic,也可以确保始终填充 cell  (具有原始状态,可以通过 `f` 进行更改) 的包装器。
        ///
        ///
        struct PutBackOnDrop<'a, T: LambdaL> {
            cell: &'a ScopedCell<T>,
            value: Option<<T as ApplyL<'static>>::Out>,
        }

        impl<'a, T: LambdaL> Drop for PutBackOnDrop<'a, T> {
            fn drop(&mut self) {
                self.cell.0.set(self.value.take().unwrap());
            }
        }

        let mut put_back_on_drop = PutBackOnDrop {
            cell: self,
            value: Some(self.0.replace(unsafe {
                let erased = mem::transmute_copy(&replacement);
                mem::forget(replacement);
                erased
            })),
        };

        f(RefMutL(put_back_on_drop.value.as_mut().unwrap()))
    }

    /// 运行 `f` 时,将 `self` 中的值设置为 `value`。
    pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R {
        self.replace(value, |_| f())
    }
}