fix: discrimination trees and "stuck" terms

See comments and new test.
This commit is contained in:
Leonardo de Moura 2022-03-05 15:11:03 -08:00
parent d39102f865
commit 613cf19509
2 changed files with 77 additions and 0 deletions

View file

@ -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 _ =>

View 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