feat: unfold nullary constants in cbv (#12646)
This PR enables the `cbv` tactic to unfold nullary (non-function) constant definitions such as `def myNat : Nat := 42`, allowing ground term evaluation (e.g. `evalEq`, `evalLT`) to recognize their values as literals. Previously, `handleConst` skipped all nullary constants. Now it performs direct delta reduction using `instantiateValueLevelParams` instead of going through the equation theorem machinery (`getUnfoldTheorem`), which would trigger `realizeConst` and fail for constants (such as derived typeclass instances) where `enableRealizationsForConst` has not been called. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8b04403830
commit
24380fc900
2 changed files with 52 additions and 6 deletions
|
|
@ -233,16 +233,16 @@ def simplifyAppFn : Simproc := fun e => do
|
|||
return .step newValue newProof
|
||||
|
||||
def handleConst : Simproc := fun e => do
|
||||
let .const n _ := e | return .rfl
|
||||
let .const n lvls := e | return .rfl
|
||||
let info ← getConstInfo n
|
||||
unless info.isDefinition do return .rfl
|
||||
let eType ← Sym.inferType e
|
||||
let eType ← whnfD eType
|
||||
unless eType matches .forallE .. do
|
||||
return .rfl
|
||||
-- TODO: Check if we need to look if we applied all the levels correctly
|
||||
let some thm ← getUnfoldTheorem n | return .rfl
|
||||
Simproc.tryCatch (fun e => Theorem.rewrite thm e) e
|
||||
if eType matches .forallE .. then return .rfl
|
||||
unless info.hasValue && info.levelParams.length == lvls.length do return .rfl
|
||||
let fBody ← instantiateValueLevelParams info lvls
|
||||
let eNew ← Sym.share fBody
|
||||
return .step eNew (← Sym.mkEqRefl eNew)
|
||||
|
||||
/--
|
||||
Pre-pass structural dispatch. Routes each expression form to the appropriate handler:
|
||||
|
|
|
|||
46
tests/lean/run/cbv_nullary.lean
Normal file
46
tests/lean/run/cbv_nullary.lean
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
set_option cbv.warning false
|
||||
|
||||
/-! Tests for `cbv` evaluation of nullary (non-function) constants.
|
||||
|
||||
Nullary definitions like `def myNat : Nat := 42` should be unfolded by `cbv`
|
||||
so that ground term evaluation (e.g. `evalEq`, `evalLT`) can recognize their
|
||||
values as literals.
|
||||
-/
|
||||
|
||||
def myNat : Nat := 42
|
||||
|
||||
-- Arithmetic: argument goes through pattern matching in Nat.add
|
||||
example : myNat + 1 = 43 := by cbv
|
||||
|
||||
-- Direct equality
|
||||
example : myNat = 42 := by cbv
|
||||
|
||||
-- Prop-level equality and comparisons
|
||||
example : (myNat = myNat) = True := by cbv
|
||||
example : (myNat = 42) = True := by cbv
|
||||
example : (myNat < 100) = True := by cbv
|
||||
example : (myNat ≤ 42) = True := by cbv
|
||||
|
||||
-- Bool-level equality
|
||||
example : (myNat == 42) = true := by cbv
|
||||
|
||||
-- Condition involving a nullary constant
|
||||
example : (if myNat = 42 then 1 else 0) = 1 := by cbv
|
||||
|
||||
-- String nullary constant
|
||||
def myStr : String := "hello"
|
||||
|
||||
example : myStr.length = 5 := by cbv
|
||||
example : (myStr = "hello") = True := by cbv
|
||||
|
||||
-- Custom inductive type
|
||||
inductive Color where | red | green | blue
|
||||
|
||||
def myColor : Color := .red
|
||||
|
||||
def colorToNat : Color → Nat
|
||||
| .red => 1
|
||||
| .green => 2
|
||||
| .blue => 3
|
||||
|
||||
example : colorToNat myColor = 1 := by cbv
|
||||
Loading…
Add table
Reference in a new issue