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
//! Sanitisers for using incremental correctly.
//!
//! These are enabled by the `nightly-incrsan` feature flag, which requires a nightly compiler.
//! They primarily work through auto-traits, which can be a bit of a pain since incremental code
//! often interfaces with other code exposing `Box<dyn Fn()>`-like APIs. So it is not enabled by
//! default.
//!
//! You can opt-in by:
//!
//! - enabling the `nightly-incrsan` feature;
//! - peppering around [`+ NotObserver`][NotObserver] bounds on things like `impl FnMut() -> ...`;
//! - wrapping foreign types in [AssertNotObserver] when you are sure they do not contain observers
// Rustc will parse things inside the cfg attribute even if the feature is not enabled.
// But #[path = "..."] will help the compiler only parse one version of this code.
//
pub use *;
/// A wrapper struct to assert that its contents are not observers, in the vein of
/// [`std::panic::AssertUnwindSafe`].
///
/// Only does anything with the `nightly-incrsan` feature enabled.
///
/// This is good if you have a `Box<dyn Trait>` you want to use somewhere, where the trait is some
/// foreign trait and you can't prove it to the compiler, but it doesn't have any observers in it.
///
/// For example:
///
/// ```
/// use incremental::*;
/// use incremental::incrsan::*;
///
/// let state = IncrState::new();
/// let constant = state.constant(1);
/// let not_observer: Box<dyn Fn()> = Box::new(|| println!("hello"));
///
/// // wrap in this to assert to the compiler it's ok, since you know what you put in the box
/// let not_observer = AssertNotObserver(not_observer);
///
/// // now you can use it freely inside map nodes, observer.subscribe() callbacks, etc
/// let map = constant.map(move |_| {
/// not_observer(); // No longer a compiler error
/// 1234
/// });
/// ```
;
/// Let the compiler check for you that T does not contain an observer.
///
/// Useful if you're about to wrap in an AssertNotObserver, and then
/// wrap in some kind of container that has no observers, that you know
/// of, but you still want to check that the type you're putting in the
/// container is `NotObserver`.
/// Adds `+ NotObserver` to the trait object if incrsan is enabled, and not otherwise.
///
/// Why? Because NotObserver can only be used that way if it is an auto-trait. Without incrsan, it
/// is a regular trait, which cannot be used in that position. Outside of trait objects, you can
/// just use it as a trait bound `<T: 'static + NotObserver>` and it is fine.
///
/// Got to wrap the traits listed after dyn with (). So Box<dyn (MyTrait)>. Just for tt-munching
/// purposes, because > is ambiguous as a terminator.
;
}
pub use not_observer_boxed_trait;