Skip to content

Commit 4a31d8a

Browse files
committed
Experiments with grind
1 parent b41dfbe commit 4a31d8a

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

src/Lean/Meta/Match/MatchEqs.lean

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Lean.Meta.Tactic.Rewrite
2020
import Lean.Meta.Constructions.SparseCasesOn
2121
import Lean.Meta.Constructions.SparseCasesOnEq
2222
import Lean.Meta.Tactic.Grind.Main
23+
import Lean.Meta.HasNotBit
2324

2425
public section
2526

@@ -29,6 +30,32 @@ private def rewriteGoalUsingEq (goal : MVarId) (eq : Expr) (symm : Bool := false
2930
let rewriteResult ← goal.rewrite (←goal.getType) eq symm
3031
goal.replaceTargetEq rewriteResult.eNew rewriteResult.eqProof
3132

33+
private def reduceSparseCasesOn (mvarId : MVarId) : MetaM (Array MVarId) := do
34+
let some (_, lhs) ← matchEqHEqLHS? (← mvarId.getType) | throwError "Target not an equality"
35+
lhs.withApp fun f xs => do
36+
let .const matchDeclName _ := f | throwError "Not a const application"
37+
let some sparseCasesOnInfo ← getSparseCasesOnInfo matchDeclName | throwError "Not a sparse casesOn application"
38+
withTraceNode `Meta.Match.matchEqs (msg := (return m!"{exceptEmoji ·} splitSparseCasesOn")) do
39+
if xs.size < sparseCasesOnInfo.arity then
40+
throwError "Not enough arguments for sparse casesOn application"
41+
let majorIdx := sparseCasesOnInfo.majorPos
42+
let major := xs[majorIdx]!
43+
let some ctorInfo ← isConstructorApp'? major
44+
| throwError "Major premise is not a constructor application:{indentExpr major}"
45+
if sparseCasesOnInfo.insterestingCtors.contains ctorInfo.name then
46+
let mvarId' ← mvarId.modifyTargetEqLHS fun lhs =>
47+
unfoldDefinition lhs
48+
return #[mvarId']
49+
else
50+
let sparseCasesOnEqName ← getSparseCasesOnEq matchDeclName
51+
let eqProof := mkConst sparseCasesOnEqName lhs.getAppFn.constLevels!
52+
let eqProof := mkAppN eqProof lhs.getAppArgs[:sparseCasesOnInfo.arity]
53+
let eqProof := mkApp eqProof (← mkHasNotBitProof (mkRawNatLit ctorInfo.cidx) (← sparseCasesOnInfo.insterestingCtors.mapM (fun n => return (← getConstInfoCtor n).cidx)))
54+
let mvarId' ← rewriteGoalUsingEq mvarId eqProof
55+
return #[mvarId']
56+
57+
58+
3259
private def splitSparseCasesOn (mvarId : MVarId) : MetaM (Array MVarId) := do
3360
let some (_, lhs) ← matchEqHEqLHS? (← mvarId.getType) | throwError "Target not an equality"
3461
lhs.withApp fun f xs => do
@@ -57,7 +84,6 @@ private def splitSparseCasesOn (mvarId : MVarId) : MetaM (Array MVarId) := do
5784
else
5885
s.mvarId.modifyTargetEqLHS fun lhs =>
5986
unfoldDefinition lhs
60-
6187
catch e =>
6288
trace[Meta.Match.matchEqs] "splitSparseCasesOn failed{indentD e.toMessageData}"
6389
throw e
@@ -148,6 +174,8 @@ where
148174
<|>
149175
(casesOnStuckLHS mvarId)
150176
<|>
177+
(reduceSparseCasesOn mvarId)
178+
<|>
151179
(splitSparseCasesOn mvarId)
152180
<|>
153181
(do let mvarId' ← simpIfTarget mvarId (useDecide := true) (useNewSemantics := true)
@@ -586,7 +614,11 @@ where go baseName := withConfig (fun c => { c with etaStruct := .none }) do
586614
let mut hs := #[]
587615
for overlappedBy in matchInfo.overlaps.overlapping i do
588616
let notAlt := notAlts[overlappedBy]!
589-
let h ← instantiateForall notAlt discrs -- We want these to be general during the proof
617+
-- We want these assumptions to be general during the proof (discrs)
618+
-- so that contradiction can recognize them,
619+
-- but specific in the final theorem (patterns)
620+
-- so that they match the splitter
621+
let h ← instantiateForall notAlt discrs
590622
-- if let some h ← simpH? h patterns.size then
591623
-- hs := hs.push h
592624
-- TODO: We still should simplify them before creating the declaration

tests/lean/run/issue11342.lean

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,46 @@ info: private theorem natToBin3.match_1.congr_eq_1.{u_1} : ∀ (motive : (x : Na
2525
-/
2626
#guard_msgs(pass trace, all) in
2727
#print sig natToBin3.match_1.congr_eq_1
28+
29+
30+
def f : List Nat → List Nat → Nat
31+
| _, 1 :: _ :: _ => 1
32+
| _, a :: _ => if a > 1 then 2 else 3
33+
| _, _ => 0
34+
35+
/--
36+
info: private theorem f.match_1.eq_2.{u_1} : ∀ (motive : List Nat → List Nat → Sort u_1) (x : List Nat) (a : Nat)
37+
(tail : List Nat) (h_1 : (x : List Nat) → (head : Nat) → (tail : List Nat) → motive x (1 :: head :: tail))
38+
(h_2 : (x : List Nat) → (a : Nat) → (tail : List Nat) → motive x (a :: tail))
39+
(h_3 : (x x_1 : List Nat) → motive x x_1),
40+
(∀ (head : Nat) (tail_1 : List Nat), a = 1 → tail = head :: tail_1 → False) →
41+
(match x, a :: tail with
42+
| x, 1 :: head :: tail => h_1 x head tail
43+
| x, a :: tail => h_2 x a tail
44+
| x, x_2 => h_3 x x_2) =
45+
h_2 x a tail
46+
-/
47+
#guard_msgs in
48+
#print sig f.match_1.eq_2
49+
50+
/--
51+
error: Failed to realize constant f.match_1.congr_eq_2:
52+
failed to generate equality theorem _private.lean.run.issue11342.0.f.match_1.congr_eq_2 for `match` expression `f.match_1`
53+
case cons.isTrue.cons
54+
motive✝ : List Nat → List Nat → Sort u_1
55+
h_1✝ : (x : List Nat) → (head : Nat) → (tail : List Nat) → motive✝ x (1 :: head :: tail)
56+
h_2✝ : (x : List Nat) → (a : Nat) → (tail : List Nat) → motive✝ x (a :: tail)
57+
h_3✝ : (x x_1 : List Nat) → motive✝ x x_1
58+
x✝¹ : List Nat
59+
a✝ : Nat
60+
tail✝¹ : List Nat
61+
x✝ : ∀ (x : List Nat) (head : Nat) (tail : List Nat), x✝¹ = x → a✝ :: tail✝¹ = 1 :: head :: tail → False
62+
head✝ : Nat
63+
tail✝ : List Nat
64+
heq_2✝ : 1 :: head✝ :: tail✝ = a✝ :: tail✝¹
65+
⊢ h_1✝ x✝¹ head✝ tail✝ ≍ h_2✝ x✝¹ a✝ tail✝¹
66+
---
67+
error: Unknown constant `f.match_1.congr_eq_2`
68+
-/
69+
#guard_msgs in
70+
#print sig f.match_1.congr_eq_2

tests/lean/run/issue9846.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ def testMatch : Array α → Unit
44

55
/--
66
error: Failed to realize constant testMatch.match_1.eq_1:
7-
failed to generate equality theorems for `match` expression `testMatch.match_1`
7+
failed to generate equality theorem _private.lean.run.issue9846.0.testMatch.match_1.eq_2 for `match` expression `testMatch.match_1`
88
case isTrue
99
α✝ : Type u_1
1010
motive✝ : Array α✝ → Sort u_2

0 commit comments

Comments
 (0)