fix: discrimination trees and "stuck" terms
See comments and new test.
This commit is contained in:
parent
d39102f865
commit
613cf19509
2 changed files with 77 additions and 0 deletions
|
|
@ -7,6 +7,7 @@ import Lean.Meta.Basic
|
|||
import Lean.Meta.FunInfo
|
||||
import Lean.Meta.InferType
|
||||
import Lean.Meta.WHNF
|
||||
import Lean.Meta.Match.MatcherInfo
|
||||
|
||||
namespace Lean.Meta.DiscrTree
|
||||
/-
|
||||
|
|
@ -369,6 +370,28 @@ private def getKeyArgs (e : Expr) (isMatch root : Bool) : MetaM (Key × Array Ex
|
|||
match e.getAppFn with
|
||||
| Expr.lit v _ => return (Key.lit v, #[])
|
||||
| Expr.const c _ _ =>
|
||||
if (← getConfig).isDefEqStuckEx && e.hasMVar then
|
||||
if (← isReducible c) then
|
||||
/- `e` is a term `c ...` s.t. `c` is reducible and `e` has metavariables, but it was not unfolded.
|
||||
This can happen if the metavariables in `e` are "blocking" smart unfolding.
|
||||
If `isDefEqStuckEx` is enabled, then we must throw the `isDefEqStuck` exception to postpone TC resolution.
|
||||
Here is an example. Suppose we have
|
||||
```
|
||||
inductive Ty where
|
||||
| bool | fn (a ty : Ty)
|
||||
|
||||
|
||||
@[reducible] def Ty.interp : Ty → Type
|
||||
| bool => Bool
|
||||
| fn a b => a.interp → b.interp
|
||||
```
|
||||
and we are trying to synthesize `BEq (Ty.interp ?m)`
|
||||
-/
|
||||
Meta.throwIsDefEqStuck
|
||||
if (← isMatcherApp e <||> isRec c) then
|
||||
/- Similar to the previous case, but for `match` and recursor applications. It may be stuck (i.e., did not reduce)
|
||||
because of metavariables. -/
|
||||
Meta.throwIsDefEqStuck
|
||||
let nargs := e.getAppNumArgs
|
||||
return (Key.const c nargs, e.getAppRevArgs)
|
||||
| Expr.fvar fvarId _ =>
|
||||
|
|
|
|||
54
tests/lean/run/stuckTC.lean
Normal file
54
tests/lean/run/stuckTC.lean
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
namespace Ex1
|
||||
|
||||
inductive Ty where
|
||||
| int
|
||||
| bool
|
||||
| fn (a ty : Ty)
|
||||
|
||||
@[reducible] def Ty.interp : Ty → Type
|
||||
| int => Int
|
||||
| bool => Bool
|
||||
| fn a b => a.interp → b.interp
|
||||
|
||||
def test {a b c : Ty} (f : a.interp → b.interp → c.interp) (x : a.interp) (y : b.interp) : c.interp :=
|
||||
f x y
|
||||
|
||||
def f (a b : Ty.bool.interp) : Ty.bool.interp :=
|
||||
test (.==.) a b
|
||||
|
||||
end Ex1
|
||||
|
||||
namespace Ex2
|
||||
|
||||
inductive Ty where
|
||||
| int
|
||||
| bool
|
||||
|
||||
@[reducible] def Ty.interp : Ty → Type
|
||||
| int => Int
|
||||
| bool => Bool
|
||||
|
||||
def test {a b c : Ty} (f : a.interp → b.interp → c.interp) (x : a.interp) (y : b.interp) : c.interp :=
|
||||
f x y
|
||||
|
||||
def f (a b : Ty.bool.interp) : Ty.bool.interp :=
|
||||
test (.==.) a b
|
||||
|
||||
end Ex2
|
||||
|
||||
namespace Ex3
|
||||
|
||||
inductive Ty where
|
||||
| int
|
||||
| bool
|
||||
|
||||
@[reducible] def Ty.interp (ty : Ty) : Type :=
|
||||
Ty.casesOn (motive := fun _ => Type) ty Int Bool
|
||||
|
||||
def test {a b c : Ty} (f : a.interp → b.interp → c.interp) (x : a.interp) (y : b.interp) : c.interp :=
|
||||
f x y
|
||||
|
||||
def f (a b : Ty.bool.interp) : Ty.bool.interp :=
|
||||
test (.==.) a b
|
||||
|
||||
end Ex3
|
||||
Loading…
Add table
Reference in a new issue