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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! Running the solver.
//!
//! The solver is a program found on PATH, not a crate. A bitvector solver taken as a dependency
//! would be the largest thing in the tree by a wide margin, it would have to hold the 1.85
//! minimum the workspace holds, and `spec/18-package-layout.md` section 18.3 asks for a reason
//! before anything is added at all. Shelling out costs a process per rule, which is nothing
//! against the solving, and it means the version in use is the version CI installed and can say.
use Write;
use ;
/// How long one query gets before the answer is [`Answer::Unknown`], in seconds.
///
/// Five minutes, and the number is measured rather than picked. Of the 571 rules the gate is
/// given, all but five are settled in well under a second each, and whole files of them come back
/// in under a second together. Four of the five are in `crates/rucc-opt/rules/safety.rules` and
/// ask about a walk over an object at sixty four bits: five seconds each for `swept` and
/// `swept.sym`, twenty for `reached`, and fifty four for `swept.down.sym`, which is the largest
/// claim in the tree. That is z3 5.1.0 on a laptop with nothing else running. The fifth is the
/// multiply against division in `crates/rucc-codegen/rules/x86-64.rules`, which no budget settles
/// and which carries a written reason for the bounded proof it gets instead.
///
/// The same solver on a six core Linux box, which is the class of machine CI runs on, costs
/// twenty four seconds for `reached` and between seventy five and eighty three for the downward
/// sweep. Eighty three against the ninety this used to be is not a budget, it is a race the
/// slower machine sometimes loses, and losing it reads as a rule nobody has proved. That is how
/// the same tree proved and failed to prove minutes apart. tamnd/rucc#949.
///
/// The cost of a limit this loose is paid only by a rule that is genuinely not going to settle,
/// and that rule stops the build either way. The cost of one too tight is a rule that is fine
/// being reported as unproved, which reads as a real problem and is not one.
const DEFAULT: u32 = 300;
/// A solver that was found.
/// What the verifier is allowed to want of a solver.
///
/// [`Solver`] is the implementation that is a solver, and it is the one the gate runs. The reason
/// there is a trait over it at all is the other kind: a test about what happens after the solver
/// gives up has no way to make the real one give up except by starving it of time, and a test
/// whose meaning depends on how fast the machine is says something slightly different everywhere
/// it runs. That is tamnd/rucc#1123. A stub that answers unknown to the one question no solver
/// settles says the thing the test is about.
///
/// Two methods, because two is what [`fn@crate::verify`] calls. This is a test double and not an
/// abstraction anybody else has to hold: nothing outside this crate implements it, and a second
/// real solver would be another [`Solver::find`] rather than another implementation of this.
/// What the solver said about one query.