Lean's `cleanupNatOffsetMajor` for recursor reduction. If the major premise is definitionally an offset `base + k` with `k > 0`, expose exactly one constructor layer as `Nat.succ (base + (k-1))`. This prevents `Nat.rec ... (x + huge)` from delta-unfolding `Nat.add` and allocating one intermediate literal per predecessor. Closed Nat arithmetic is left alone so the primitive Nat reducer can compute
(
&mut self,
e: &KExpr<M>,
)
| 1123 | // and may leave the Prj head stuck; `try_proj_app_reduce` gives it |
| 1124 | // one more attempt with the same projection policy. |
| 1125 | if let Some((proj_result, args)) = |
| 1126 | self.try_proj_app_reduce(&cur, flags)? |
| 1127 | { |
| 1128 | let mut result = proj_result; |
| 1129 | for arg in &args { |
| 1130 | result = self.intern(KExpr::app(result, arg.clone())); |
| 1131 | } |
| 1132 | cur = result; |
| 1133 | continue; |
| 1134 | } |
| 1135 | |
| 1136 | // Primitive reduction, dispatched by memoized head family (see the |
| 1137 | // main WHNF loop) — family head sets are disjoint, so dispatching |
| 1138 | // replaces probe-everything without changing semantics. |
| 1139 | let family = self.head_prim_family(&cur); |
| 1140 | |
| 1141 | // BitVec.toNat/ult reductions are definitional wrappers around Nat. |
| 1142 | if family == PrimFamily::BitVec |
| 1143 | && let Some(reduced) = self.try_reduce_bitvec(&cur)? |
| 1144 | { |
| 1145 | cur = reduced; |
| 1146 | continue; |
| 1147 | } |
| 1148 | |
| 1149 | // Nat primitive reduction |
| 1150 | if family == PrimFamily::Nat |
no test coverage detected