@@ -20,6 +20,7 @@ import Lean.Meta.Tactic.Rewrite
2020import Lean.Meta.Constructions.SparseCasesOn
2121import Lean.Meta.Constructions.SparseCasesOnEq
2222import Lean.Meta.Tactic.Grind.Main
23+ import Lean.Meta.HasNotBit
2324
2425public 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+
3259private 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
0 commit comments