Skip to content

Commit f9dcdeb

Browse files
committed
[ENH] Add a tool to reason through the state space of bootstrap.
The space of cases I have to handle: panic(BenignRace, AlreadyInitialized, Uninitialized) -> cannot double-initialize manifest panic(BenignRace, AlreadyInitialized, Failure) -> cannot double-initialize manifest panic(BenignRace, AlreadyInitialized, Success) -> cannot double-initialize manifest panic(Success, AlreadyInitialized, Uninitialized) -> cannot double-initialize manifest panic(Success, AlreadyInitialized, Failure) -> cannot double-initialize manifest panic(Success, AlreadyInitialized, Success) -> cannot double-initialize manifest panic(BenignRace, Uninitialized, Failure) -> failed to install recovered manifest panic(BenignRace, Success, Failure) -> failed to install recovered manifest panic(Success, Uninitialized, Failure) -> failed to install recovered manifest panic(Success, Success, Failure) -> failed to install recovered manifest panic(BenignRace, Uninitialized, Uninitialized) -> cannot have manifest become uninitialized panic(BenignRace, Success, Uninitialized) -> cannot have manifest become uninitialized panic(Success, Uninitialized, Uninitialized) -> cannot have manifest become uninitialized panic(Success, Success, Uninitialized) -> cannot have manifest become uninitialized Committing so I don't lose it.
1 parent 573b791 commit f9dcdeb

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//! This file is not intended for public consumption, but is kept for completeness.
2+
//!
3+
//! In this file you will find that we reason about the bootstrap process by completely exploring
4+
//! the state space and pruning known good states. The goal is to prune every state or print a
5+
//! list of states that are bad.
6+
//!
7+
//! This is ad-hoc machine-assisted proving without an environment or theorem prover.
8+
9+
#[derive(Clone, Copy, Debug)]
10+
enum FragmentState {
11+
BenignRace,
12+
Conflict,
13+
Success,
14+
}
15+
16+
impl FragmentState {
17+
fn all_states() -> impl Iterator<Item = Self> {
18+
vec![
19+
FragmentState::BenignRace,
20+
FragmentState::Conflict,
21+
FragmentState::Success,
22+
]
23+
.into_iter()
24+
}
25+
}
26+
27+
#[derive(Clone, Copy, Debug)]
28+
enum InitializeManifest {
29+
Uninitialized,
30+
AlreadyInitialized,
31+
Success,
32+
}
33+
34+
impl InitializeManifest {
35+
fn all_states() -> impl Iterator<Item = Self> {
36+
vec![
37+
InitializeManifest::Uninitialized,
38+
InitializeManifest::AlreadyInitialized,
39+
InitializeManifest::Success,
40+
]
41+
.into_iter()
42+
}
43+
}
44+
45+
#[derive(Clone, Copy, Debug)]
46+
enum RecoverManifest {
47+
Uninitialized,
48+
Failure,
49+
Success,
50+
}
51+
52+
impl RecoverManifest {
53+
fn all_states() -> impl Iterator<Item = Self> {
54+
vec![
55+
RecoverManifest::Uninitialized,
56+
RecoverManifest::Failure,
57+
RecoverManifest::Success,
58+
]
59+
.into_iter()
60+
}
61+
}
62+
63+
enum Disposition {
64+
/// The combination of states is considered a good case.
65+
Good,
66+
/// The combination of states is not considered by the rule.
67+
Pass,
68+
/// The case can be dropped with good conscience for not mattering. The string is the reason.
69+
Drop(
70+
&'static str,
71+
FragmentState,
72+
InitializeManifest,
73+
RecoverManifest,
74+
),
75+
/// The case must lead to an error at runtime.
76+
Panic(
77+
&'static str,
78+
FragmentState,
79+
InitializeManifest,
80+
RecoverManifest,
81+
),
82+
/// The case must be raised to the user for inspection.
83+
Raise(
84+
&'static str,
85+
FragmentState,
86+
InitializeManifest,
87+
RecoverManifest,
88+
),
89+
}
90+
91+
fn happy_paths(fs: FragmentState, im: InitializeManifest, rm: RecoverManifest) -> Disposition {
92+
match (fs, im, rm) {
93+
(
94+
FragmentState::Success | FragmentState::BenignRace,
95+
InitializeManifest::Uninitialized | InitializeManifest::Success,
96+
RecoverManifest::Success,
97+
) => Disposition::Good,
98+
_ => Disposition::Pass,
99+
}
100+
}
101+
102+
fn error_paths(fs: FragmentState, im: InitializeManifest, rm: RecoverManifest) -> Disposition {
103+
match (fs, im, rm) {
104+
(_, InitializeManifest::AlreadyInitialized, _) => {
105+
Disposition::Panic("cannot double-initialize manifest", fs, im, rm)
106+
}
107+
(_, _, RecoverManifest::Uninitialized) => {
108+
Disposition::Panic("cannot have manifest become uninitialized", fs, im, rm)
109+
}
110+
(_, _, RecoverManifest::Failure) => {
111+
Disposition::Panic("failed to install recovered manifest", fs, im, rm)
112+
}
113+
_ => Disposition::Pass,
114+
}
115+
}
116+
117+
fn conflict_on_fragment(
118+
fs: FragmentState,
119+
im: InitializeManifest,
120+
rm: RecoverManifest,
121+
) -> Disposition {
122+
if matches!(fs, FragmentState::Conflict) {
123+
Disposition::Drop(
124+
"no need to touch manifest if fragment conflicts",
125+
fs,
126+
im,
127+
rm,
128+
)
129+
} else {
130+
Disposition::Pass
131+
}
132+
}
133+
134+
fn unconditionally_raise(
135+
fs: FragmentState,
136+
im: InitializeManifest,
137+
rm: RecoverManifest,
138+
) -> Disposition {
139+
Disposition::Raise("unconditional raise", fs, im, rm)
140+
}
141+
142+
pub fn main() {
143+
let mut states = vec![];
144+
for fs in FragmentState::all_states() {
145+
for im in InitializeManifest::all_states() {
146+
for rm in RecoverManifest::all_states() {
147+
states.push((fs, im, rm));
148+
}
149+
}
150+
}
151+
let rules = vec![
152+
happy_paths,
153+
conflict_on_fragment,
154+
error_paths,
155+
unconditionally_raise,
156+
];
157+
for state in states.iter() {
158+
for rule in &rules {
159+
match (rule)(state.0, state.1, state.2) {
160+
Disposition::Pass => {}
161+
Disposition::Good => {
162+
break;
163+
}
164+
Disposition::Panic(reason, fs, im, rm) => {
165+
println!("panic({fs:?}, {im:?}, {rm:?}) -> {reason}");
166+
break;
167+
}
168+
Disposition::Drop(_, _, _, _) => {
169+
break;
170+
}
171+
Disposition::Raise(reason, fs, im, rm) => {
172+
println!("raise({fs:?}, {im:?}, {rm:?}) -> {reason}");
173+
break;
174+
}
175+
}
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)