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
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#![cfg_attr(feature = "nightly",
    feature(external_doc),
    doc(include = "../README.md")
)]
#![allow(nonstandard_style)]

#[must_use = "You need to call `.try_eval()`"]
pub
const
fn with_state<State> (state: State)
  -> Runner<State>
{
    Runner { state }
}

pub
struct Runner<State> {
    state: State,
}

pub
struct RunnerWithTryEval<State, try_eval> {
    state: State,
    try_eval: try_eval,
}

impl<State> Runner<State> {
    #[must_use =
        "`.try_eval()` is lazy and does nothing: you need to call `.finally()`"
    ]
    pub
    fn try_eval<R, try_eval> (
        self: Runner<State>,
        __: try_eval,
    ) -> RunnerWithTryEval<State, try_eval>
    where
        try_eval: FnOnce(&'_ mut State) -> R,
    {
        let Runner { state } = self;
        RunnerWithTryEval {
            state,
            try_eval: __,
        }
    }

    #[doc(hidden)] pub
    fn finally<R, F> (
        self: Runner<State>,
        _: F,
    ) -> R
    where
        Self : __::missing_try_eval<F>,
    {
        <Self as __::missing_try_eval<F>>::unreachable()
    }
}

mod __ {
    pub trait missing_try_eval<F> {
        fn unreachable() -> !;
    }
}

impl<State, try_eval> RunnerWithTryEval<State, try_eval> {
    pub
    fn finally<R, finally> (
        self: RunnerWithTryEval<State, try_eval>,
        __: finally,
    ) -> R
    where
        try_eval: FnOnce(&'_ mut State) -> R,
        finally: FnOnce(State),
    {
        use ::core::mem::ManuallyDrop as MD;

        struct WithDrop<State, Finally>
        where
            Finally : FnOnce(State),
        {
            state: MD<State>,
            finally: MD<Finally>,
        }

        impl<State, Finally> Drop for WithDrop<State, Finally>
        where
            Finally : FnOnce(State),
        {
            fn drop (self: &'_ mut Self)
            {
                unsafe {
                    let state = MD::take(&mut self.state);
                    let finally = MD::take(&mut self.finally);
                    let () = finally(state);
                }
            }
        }

        let RunnerWithTryEval { state, try_eval } = self;
        let ref mut state_with_drop = WithDrop {
            state: MD::new(state),
            finally: MD::new(__),
        };
        try_eval(&mut state_with_drop.state)
    }
}

#[cfg(all(doc, feature = "nightly"))]
#[doc(include = "compile_fail_tests.md")]
mod compile_fail_tests {}