diff --git a/src/Lean/Meta/Tactic/Grind/CasesMatch.lean b/src/Lean/Meta/Tactic/Grind/CasesMatch.lean index 8653c3f5cf..c056c6444b 100644 --- a/src/Lean/Meta/Tactic/Grind/CasesMatch.lean +++ b/src/Lean/Meta/Tactic/Grind/CasesMatch.lean @@ -13,10 +13,40 @@ import Lean.Meta.Tactic.Grind.Simp public section namespace Lean.Meta.Grind -/-- Returns `true` if `e` is of the form `∀ ..., _ = _ ... -> False` -/ -def isMatchCondCandidate (e : Expr) : Bool := - -- TODO: see comment at the beginning of `MatchCond.lean`. - Simp.isEqnThmHypothesis e +/-- +Returns `true` if `e` is of the form `∀ ..., _ = _ ... -> False`. +The lhs of each equation must not have loose bound variables. +Recall that the `lhs` should correspond to variables in a given alternative. +For example, the given match-condition +``` +∀ (head : Nat) (tail : List Nat), a = 1 → as = head :: tail → False +``` +is generated for the second alternative at +``` +def f : List Nat → List Nat → Nat + | _, 1 :: _ :: _ => ... + | _, a :: as => ... + | _, _ => ... +``` +That is, `a` must be different from `1`, or `as` must not be of the form `_ :: _`. That is, +they must not be a match for the first alternative. +**Note**: We were *not* previously checking whether the `lhs` did not have loose bound variables. +This missing check caused a panic at `tryToProveFalse` function at `MatchCond.lean` because +it assumes the `lhs` does not have loose bound variables. +**Note**: This function is an approximation. It may return `true` for terms that do not +correspond to match-conditions. +-/ +partial def isMatchCondCandidate (e : Expr) : Bool := + e.isForall && go e +where + go (e : Expr) : Bool := + if let .forallE _ d b _ := e then + match_expr d with + | Eq _ lhs _ => !lhs.hasLooseBVars && go b + | HEq _ lhs _ _ => !lhs.hasLooseBVars && go b + | _ => b.hasLooseBVar 0 && go b + else + e.isFalse /-- Given a splitter alternative, annotate the terms that are `match`-expression diff --git a/tests/lean/run/grind_match_cond_issue.lean b/tests/lean/run/grind_match_cond_issue.lean new file mode 100644 index 0000000000..05ac242a7f --- /dev/null +++ b/tests/lean/run/grind_match_cond_issue.lean @@ -0,0 +1,20 @@ +/-- +error: `grind` failed +case grind.2.2.1.1 +n m a : Nat +ih : ∀ {a : Nat}, ¬a ^ 2 = 4 ^ m * n +h : a ^ 2 = 4 ^ (m + 1) * n +h_1 : ¬4 * 4 ^ m = 4 ^ m +h_2 : ¬4 * 4 ^ m = 4 ^ m +h_3 : n = 4 ^ m +h_4 : ↑a = 4 +⊢ False +-/ +#guard_msgs in +example {n m a : Nat} (ih : ∀ {a : Nat}, a ^ 2 = 4 ^ m * n → False) + (h : a ^ 2 = 4 ^ (m + 1) * n) : False := by + grind -verbose + +example {n m a : Nat} (ih : ∀ {a : Nat}, a ^ 2 = 4 ^ m * n → False) + (h : a ^ 2 = 4 ^ m * n) : False := by + grind