lean4-htt/tests/lean/run/cbv_dep_proj.lean
Wojciech Różowski 14e1d4328f
fix: prevent cbv crash on dependent projections with @[cbv_eval] rewrites (#12612)
This PR fixes a crash in the `cbv` tactic's `handleProj` simproc when
processing a dependent projection (e.g. `Sigma.snd`) whose struct is
rewritten via `@[cbv_eval]` to a non-definitionally-equal term that
cannot be further reduced.

- Previously, `handleProj` returned `.rfl (done := false)`, causing the
`.proj` expression to flow into `simpStep` which throws "unexpected
kernel projection term"
- The fix marks the result as `done := true` so that `cbv` gracefully
gets stuck instead of crashing
- Adds regression tests for dependent projections on `Sigma`, custom
structures, and `Subtype`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:38:15 +00:00

73 lines
2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

set_option cbv.warning false
/-! Tests for `cbv` handling of dependent projections.
When a struct is rewritten (e.g. via `@[cbv_eval]`) but the projection is
dependent and the original struct can't be reduced, `cbv` should gracefully
get stuck rather than crash.
-/
-- Sigma: .1 is non-dependent, .2 is dependent
def myPair : Σ n : Nat, Fin (n + 1) := ⟨5, ⟨3, by omega⟩⟩
axiom otherPair : Σ n : Nat, Fin (n + 1)
@[cbv_eval ←] axiom otherPair_eq : myPair = otherPair
example : otherPair.1 = 5 := by cbv
/--
error: unsolved goals
⊢ otherPair.2.1 = 3
-/
#guard_msgs in
example : otherPair.2.val = 3 := by cbv
-- Custom structure with a dependent field
structure DepPkg where
n : Nat
val : Fin (n + 1)
def concretePkg : DepPkg := ⟨5, ⟨3, by omega⟩⟩
axiom opaquePkg : DepPkg
@[cbv_eval ←] axiom opaquePkg_eq : concretePkg = opaquePkg
example : opaquePkg.n = 5 := by cbv
/--
error: unsolved goals
⊢ opaquePkg.2.1 = 3
-/
#guard_msgs in
example : opaquePkg.val.val = 3 := by cbv
-- Subtype: .val is non-dependent, so the rewrite goes through
def concreteSubtype : { n : Nat // n > 0 } := ⟨5, by omega⟩
axiom opaqueSubtype : { n : Nat // n > 0 }
@[cbv_eval ←] axiom opaqueSubtype_eq : concreteSubtype = opaqueSubtype
example : opaqueSubtype.val = 5 := by cbv
-- Non-dependent projections: function projected from a structure and applied
structure FnStruct where
fn : Nat → Nat
def myFnStruct : FnStruct := ⟨fun n => n + 1⟩
example : myFnStruct.fn 5 = 6 := by cbv
-- Nested non-dependent projections
structure Layer1 where val : Nat
structure Layer2 where inner : Layer1
structure Layer3 where inner : Layer2
def nested : Layer3 := ⟨⟨⟨42⟩⟩⟩
example : nested.inner.inner.val = 42 := by cbv
-- Double projection through a product
structure FnPairS where
fst : Nat → Nat
snd : Nat → Nat
def fnPairPair : FnPairS × FnPairS :=
(⟨fun n => n + 1, fun n => n + 2⟩, ⟨fun n => n + 3, fun n => n + 4⟩)
example : fnPairPair.1.fst 5 = 6 := by cbv
example : fnPairPair.2.snd 5 = 9 := by cbv