Commit 6bfc273
authored
Warn when quantifier range exceeds SAT solver threshold (#4579)
Emit a compile-time warning when an unbounded `forall!` or `exists!`
quantifier is detected. SAT solvers (the default backend) expand
quantifiers into one conjunction/disjunction per value in the range, so
unbounded ranges (`forall!(|i| ...)` which expands over all 2^64 `usize`
values) cause silent memory exhaustion or divergence with no diagnostic.
Contributes to #3273.
## Problem
Writing `forall!(|i| ...)` (unbounded, ranging over all `usize` values)
with the default SAT backend silently hangs or OOMs because CBMC expands
the quantifier into 2^64 terms. Users get no feedback about why
verification doesn't terminate.
## Solution
- **`warn_large_quantifier_range()`** in `hooks.rs`: At codegen time,
checks if both quantifier bounds are compile-time integer constants. If
the range exceeds `QUANTIFIER_RANGE_WARN_THRESHOLD` (1000), emits a
`span_warn` suggesting tighter bounds or an SMT solver. For unbounded
ranges (~2^64), uses a human-friendly message instead of the raw
integer.
- **`unwrap_to_constant()`**: Helper that unwraps typecasts and resolves
symbol references via the symbol table to extract integer constants from
bound expressions. Includes a depth limit (5) to guard against cycles.
### Known limitation
Bounded quantifiers (`forall!(|i in (0, 2000)| ...)`) use `let` bindings
in the macro expansion for type coercion, which hides the constant
values from codegen. The warning currently only fires for **unbounded**
quantifiers, which is the most dangerous case. Detecting large bounded
ranges would require constant propagation through local variables, a
potential follow-up improvement.
## Example warning
```
warning: `kani::forall` has an unbounded (~2^64) range; SAT solvers (the default
backend) expand quantifiers over every value and may exhaust memory or
diverge. Consider adding tighter bounds or using an SMT solver
(`#[kani::solver(z3)]` or `--solver z3`).
--> tests/expected/quantifiers/large_range_warning.rs:15:13
```
## Testing
- `large_range_warning.rs` — expected test with 3 harnesses:
- `check_unbounded_forall_warns`: unbounded `forall!(|i| ...)`, verifies
warning is emitted
- `check_unbounded_exists_warns`: unbounded `exists!(|i| ...)`, verifies
warning is emitted
- `check_small_forall_no_warn`: range of 10, verifies no warning
(absence of output is intentional)
---
By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.1 parent d2c6dca commit 6bfc273
3 files changed
Lines changed: 119 additions & 0 deletions
File tree
- kani-compiler/src/codegen_cprover_gotoc/overrides
- tests/expected/quantifiers
Lines changed: 86 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
957 | 957 | | |
958 | 958 | | |
959 | 959 | | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
960 | 966 | | |
961 | 967 | | |
962 | 968 | | |
| |||
1121 | 1127 | | |
1122 | 1128 | | |
1123 | 1129 | | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
1124 | 1210 | | |
1125 | 1211 | | |
1126 | 1212 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
0 commit comments