fix: handle AppBuilderException in cbv tactic if the projection function is dependent (#12460)
This PR fixes an `AppBuilder` exception in the `cbv` tactic when simplifying projections whose projection function is dependent (closes #12457). Previously, `handleProj` unconditionally used `mkCongrArg` to prove `e.i = e'.i` from `e = e'`, but `mkCongrArg` requires a non-dependent function. For dependent projections (e.g., `fun x => x.2 : (x : String.Slice) → x.1.Pos`), this would fail. Now, `handleProj` first checks whether the projection function type is non-dependent (a simple arrow). If so, it proceeds with `mkCongrArg` as before. Otherwise, it falls back to: 1. Attempting to reduce the projection directly. 2. If reduction fails, using a heterogeneous congruence lemma (`mkHCongr`) converted to an equality via `mkEqOfHEq`, provided the original and rewritten struct are definitionally equal.
This commit is contained in:
parent
f3b8f76ec4
commit
dae150a976
2 changed files with 24 additions and 4 deletions
|
|
@ -120,10 +120,29 @@ def handleProj : Simproc := fun e => do
|
|||
| .step e' proof _ =>
|
||||
let type ← Sym.inferType e'
|
||||
let congrArgFun := Lean.mkLambda `x .default type <| .proj typeName idx <| .bvar 0
|
||||
|
||||
-- TODO: Create an efficient symbolic version of `mkCongrArg`
|
||||
let newProof ← mkCongrArg congrArgFun proof
|
||||
return .step (← Lean.Expr.updateProjS! e e') newProof
|
||||
let congrArgFunType ← inferType congrArgFun
|
||||
-- If the type of a projection function is non-dependent, we can safely prove `e.i = e'.i` from `e = e'`
|
||||
if (congrArgFunType.isArrow) then
|
||||
let newProof ← mkCongrArg congrArgFun proof
|
||||
return .step (← Lean.Expr.updateProjS! e e') newProof
|
||||
else
|
||||
-- If the type of the projection function is dependent, we first try to reduce the projection
|
||||
let reduced ← reduceProj? e
|
||||
match reduced with
|
||||
| .some reduced =>
|
||||
let reduced ← Sym.share reduced
|
||||
return .step reduced (← Sym.mkEqRefl reduced)
|
||||
| .none =>
|
||||
-- If we failed to reduce it, we turn to a last resort; we try use heterogenous congruence lemma that we then try to turn into an equality.
|
||||
unless (← isDefEq struct e') do
|
||||
-- If we rewrote the projection body using something that holds up to propositional equality, then there is nothing we can do.
|
||||
-- TODO: Check if there is a need to report this to a user, or shall we fail silently.
|
||||
return .rfl
|
||||
let hcongr ← mkHCongr congrArgFun
|
||||
let newProof := mkApp3 (hcongr.proof) struct e' proof
|
||||
-- We have already checked if `struct` and `e'` are defEq, so we can skip the check.
|
||||
let newProof ← mkEqOfHEq newProof (check := false)
|
||||
return .step (← Lean.Expr.updateProjS! e e') newProof
|
||||
|
||||
def simplifyAppFn : Simproc := fun e => do
|
||||
unless e.isApp do return .rfl
|
||||
|
|
|
|||
1
tests/lean/run/12457.lean
Normal file
1
tests/lean/run/12457.lean
Normal file
|
|
@ -0,0 +1 @@
|
|||
example : ("abc".pos ⟨1⟩ (by decide_cbv)).get (by decide_cbv) = 'b' := by decide_cbv
|
||||
Loading…
Add table
Reference in a new issue