fix: cases tactic to handle non-atomic eliminator well (#8361)

This PR fixes a bug in the `cases` tacic introduced in #3188 that arises
when cases (not induction) is used with a non-atomic expression in using
and the argument indexing gets confused.

This fixes #8360.
This commit is contained in:
Joachim Breitner 2025-05-15 18:59:11 +02:00 committed by GitHub
parent 3481f43130
commit e5393cf6bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 7 deletions

View file

@ -128,10 +128,11 @@ private def getFType : M Expr := do
pure fType
structure Result where
elimApp : Expr
motive : MVarId
alts : Array Alt
others : Array MVarId
elimApp : Expr
elimArgs : Array Expr
motive : MVarId
alts : Array Alt
others : Array MVarId
complexArgs : Array Expr
/--
@ -209,7 +210,10 @@ partial def mkElimApp (elimInfo : ElimInfo) (targets : Array Expr) (tag : Name)
unless targets.contains motiveArg do
throwError "mkElimApp: Expected first {targets.size} arguments of motive in conclusion to be one of the targets:{indentExpr s.fType}"
pure motiveArgs[targets.size:]
return { elimApp := (← instantiateMVars s.f), alts, others, motive, complexArgs }
let elimApp ← instantiateMVars s.f
-- `elimArgs` is the argument list that the offsets in `elimInfo` work with
let elimArgs := elimApp.getAppArgs[elimInfo.elimExpr.getAppNumArgs:]
return { elimApp, elimArgs, alts, others, motive, complexArgs }
/--
Given a goal `... targets ... |- C[targets, complexArgs]` associated with `mvarId`,
@ -981,7 +985,7 @@ def evalCasesCore (stx : Syntax) (elimInfo : ElimInfo) (targets : Array Expr)
let tag ← mvarId.getTag
mvarId.withContext do
let result ← withRef targetRef <| ElimApp.mkElimApp elimInfo targets tag
let elimArgs := result.elimApp.getAppArgs
let elimArgs := result.elimArgs
let targets ← elimInfo.targetsPos.mapM fun i => instantiateMVars elimArgs[i]!
let motiveType ← inferType elimArgs[elimInfo.motivePos]!
let mvarId ← generalizeTargetsEq mvarId motiveType targets

View file

@ -62,7 +62,7 @@ def getElimExprInfo (elimExpr : Expr) (baseDeclName? : Option Name := none) : Me
let motiveType ← inferType motive
forallTelescopeReducing motiveType fun motiveParams motiveResultType => do
unless motiveParams.size == motiveArgs.size do
throwError "expecetd {motiveArgs.size} parameters at motive type, got {motiveParams.size}:{indentExpr motiveType}"
throwError "expected {motiveArgs.size} parameters at motive type, got {motiveParams.size}:{indentExpr motiveType}"
unless motiveResultType.isSort do
throwError "motive result type must be a sort{indentExpr motiveType}"
let some motivePos ← pure (xs.idxOf? motive) |

View file

@ -0,0 +1,7 @@
axiom thm.{u_1, u_2} {α : Type u_1} {β : Type u_2} (f : α → β)
(motive : List α → List β → Prop) (case1 : motive [] [])
(case2 : ∀ (a : α) (as : List α), motive (a :: as) (f a :: List.map f as)) (l : List α) : motive l (List.map f l)
theorem map_isNil (f : α → β) (l : List α) :
List.map f l = [] ↔ l = [] := by
cases l using thm f <;> simp