]>
git.proxmox.com Git - rustc.git/blob - library/proc_macro/src/bridge/scoped_cell.rs
1 //! `Cell` variant for (scoped) existential lifetimes.
5 use std
::ops
::{Deref, DerefMut}
;
7 /// Type lambda application, with a lifetime.
8 #[allow(unused_lifetimes)]
13 /// Type lambda taking a lifetime, i.e., `Lifetime -> Type`.
14 pub trait LambdaL
: for<'a
> ApplyL
<'a
> {}
16 impl<T
: for<'a
> ApplyL
<'a
>> LambdaL
for T {}
18 // HACK(eddyb) work around projection limitations with a newtype
19 // FIXME(#52812) replace with `&'a mut <T as ApplyL<'b>>::Out`
20 pub struct RefMutL
<'a
, 'b
, T
: LambdaL
>(&'a
mut <T
as ApplyL
<'b
>>::Out
);
22 impl<'a
, 'b
, T
: LambdaL
> Deref
for RefMutL
<'a
, 'b
, T
> {
23 type Target
= <T
as ApplyL
<'b
>>::Out
;
24 fn deref(&self) -> &Self::Target
{
29 impl<'a
, 'b
, T
: LambdaL
> DerefMut
for RefMutL
<'a
, 'b
, T
> {
30 fn deref_mut(&mut self) -> &mut Self::Target
{
35 pub struct ScopedCell
<T
: LambdaL
>(Cell
<<T
as ApplyL
<'
static>>::Out
>);
37 impl<T
: LambdaL
> ScopedCell
<T
> {
38 pub const fn new(value
: <T
as ApplyL
<'
static>>::Out
) -> Self {
39 ScopedCell(Cell
::new(value
))
42 /// Sets the value in `self` to `replacement` while
43 /// running `f`, which gets the old value, mutably.
44 /// The old value will be restored after `f` exits, even
45 /// by panic, including modifications made to it by `f`.
46 pub fn replace
<'a
, R
>(
48 replacement
: <T
as ApplyL
<'a
>>::Out
,
49 f
: impl for<'b
, 'c
> FnOnce(RefMutL
<'b
, 'c
, T
>) -> R
,
51 /// Wrapper that ensures that the cell always gets filled
52 /// (with the original state, optionally changed by `f`),
53 /// even if `f` had panicked.
54 struct PutBackOnDrop
<'a
, T
: LambdaL
> {
55 cell
: &'a ScopedCell
<T
>,
56 value
: Option
<<T
as ApplyL
<'
static>>::Out
>,
59 impl<'a
, T
: LambdaL
> Drop
for PutBackOnDrop
<'a
, T
> {
61 self.cell
.0.set(self.value
.take().unwrap());
65 let mut put_back_on_drop
= PutBackOnDrop
{
67 value
: Some(self.0.replace(unsafe {
68 let erased
= mem
::transmute_copy(&replacement
);
69 mem
::forget(replacement
);
74 f(RefMutL(put_back_on_drop
.value
.as_mut().unwrap()))
77 /// Sets the value in `self` to `value` while running `f`.
78 pub fn set
<R
>(&self, value
: <T
as ApplyL
<'_
>>::Out
, f
: impl FnOnce() -> R
) -> R
{
79 self.replace(value
, |_
| f())