lean4-htt/tests/lean/run/sparseCasesOn.lean
Joachim Breitner 27e5e21bfe
perf: use Nat-based bitmask in sparse cases construction (#11200)
This PR changes how sparse case expressions represent the
none-of-the-above information. Instead of of many `x.ctorIdx ≠ i`
hypotheses, it introduces a single `Nat.hasNotBit mask x.ctorIdx`
hypothesis which compresses that information into a bitmask. This avoids
a quadratic overhead during splitter generation, where all n assumptions
would be refined through `.subst` and `.cases` constructions for all n
assumption of the splitter alternative.

The definition of `Nat.hasNotBit` uses `Nat.rightShift` which is fiddly
to get to reduce well, especially on open terms and with `Meta.whnf`.
Some experimentation was needed to find proof terms that work, these are
all put together in the `Lean.Meta.HasNotBit` module.

Fixes #11183

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
2025-11-17 10:05:18 +00:00

45 lines
1.3 KiB
Text

import Lean
/-- info: test._sparseCasesOn_1 -/
#guard_msgs in
run_meta
Lean.withDeclNameForAuxNaming `test do
let name ← Lean.Meta.mkSparseCasesOn ``Lean.Expr #[``Lean.Expr.fvar, ``Lean.Expr.sort]
Lean.logInfo m!"{name}"
/--
info: test._sparseCasesOn_1.{u} {motive : Lean.Expr → Sort u} (t : Lean.Expr)
(fvar : (fvarId : Lean.FVarId) → motive (Lean.Expr.fvar fvarId))
(sort : (u : Lean.Level) → motive (Lean.Expr.sort u)) : (Nat.hasNotBit 10 t.ctorIdx → motive t) → motive t
-/
#guard_msgs in
#check test._sparseCasesOn_1
/-- error: mkSparseCasesOn: unexpected number of universe parameters in `Or.casesOn` -/
#guard_msgs in
run_meta
Lean.withDeclNameForAuxNaming `test do
let name ← Lean.Meta.mkSparseCasesOn ``Or #[``Or.inl]
Lean.logInfo m!"{name}"
/- Check that the compiler is producin good code -/
set_option trace.Compiler.saveBase true
/--
trace: [Compiler.saveBase] size: 7
def testDecl motive t fvar sort x.1 : motive lcAny :=
cases t : motive lcAny
| Lean.Expr.fvar fvarId =>
let _x.2 := fvar fvarId;
return _x.2
| Lean.Expr.sort u =>
let _x.3 := sort u;
return _x.3
| _ =>
let _x.4 := x.1 _;
return _x.4
-/
#guard_msgs in
def testDecl := @test._sparseCasesOn_1