fix: induction: do not allow generalizing variables occurring in the using clause (#10697)
This PR lets `induction` print a warning if a variable occurring in the `using` clause is generalized. Fixes #10683.
This commit is contained in:
parent
486d93c5fd
commit
5a751d4688
2 changed files with 28 additions and 5 deletions
|
|
@ -586,14 +586,17 @@ private def getUserGeneralizingFVarIds (stx : Syntax) : TacticM (Array FVarId) :
|
|||
getFVarIds vars
|
||||
|
||||
-- process `generalizingVars` subterm of induction Syntax `stx`.
|
||||
private def generalizeVars (mvarId : MVarId) (stx : Syntax) (targets : Array Expr) : TacticM (Array FVarId × MVarId) :=
|
||||
private def generalizeVars (mvarId : MVarId) (stx : Syntax) (targets : Array Expr) (elimExpr : Expr) : TacticM (Array FVarId × MVarId) :=
|
||||
mvarId.withContext do
|
||||
let userFVarIds ← getUserGeneralizingFVarIds stx
|
||||
let forbidden ← mkGeneralizationForbiddenSet targets
|
||||
let mut s ← getFVarSetToGeneralize targets forbidden
|
||||
let forbidden1 ← mkGeneralizationForbiddenSet targets
|
||||
let forbidden2 ← mkGeneralizationForbiddenSet #[elimExpr]
|
||||
let mut s ← getFVarSetToGeneralize targets (forbidden1.union forbidden2)
|
||||
for userFVarId in userFVarIds do
|
||||
if forbidden.contains userFVarId then
|
||||
if forbidden1.contains userFVarId then
|
||||
throwError "Variable `{mkFVar userFVarId}` cannot be generalized because the induction target depends on it"
|
||||
if forbidden2.contains userFVarId then
|
||||
throwError "Variable `{mkFVar userFVarId}` cannot be generalized because the induction principle depends on it"
|
||||
if s.contains userFVarId then
|
||||
throwOrLogError m!"Unnecessary `generalizing` argument: Variable `{mkFVar userFVarId}` is generalized automatically"
|
||||
s := s.insert userFVarId
|
||||
|
|
@ -947,7 +950,7 @@ private def evalInductionCore (stx : Syntax) (elimInfo : ElimInfo) (targets : Ar
|
|||
mvarId.withContext do
|
||||
checkInductionTargets targets
|
||||
let targetFVarIds := targets.map (·.fvarId!)
|
||||
let (generalized, mvarId) ← generalizeVars mvarId stx targets
|
||||
let (generalized, mvarId) ← generalizeVars mvarId stx targets elimInfo.elimExpr
|
||||
mvarId.withContext do
|
||||
let result ← withRef stx[1] do -- use target position as reference
|
||||
ElimApp.mkElimApp elimInfo targets tag
|
||||
|
|
|
|||
20
tests/lean/run/issue10683.lean
Normal file
20
tests/lean/run/issue10683.lean
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
def orderedInsert (a : Nat) : List Nat → List Nat
|
||||
| [] => [a]
|
||||
| b :: l => if a < b then a :: b :: l else b :: orderedInsert a l
|
||||
|
||||
/-- error: Variable `x` cannot be generalized because the induction principle depends on it -/
|
||||
#guard_msgs in
|
||||
example : orderedInsert x l = [] := by
|
||||
induction l using orderedInsert.induct_unfolding (a := x) generalizing x
|
||||
|
||||
/-- error: Variable `x` cannot be generalized because the induction principle depends on it -/
|
||||
#guard_msgs in
|
||||
example : orderedInsert x l = [] := by
|
||||
fun_induction orderedInsert generalizing x
|
||||
|
||||
axiom foo_induct (n : Nat) {motive : Nat → Prop} (h : ∀ m, n = m): ∀ m, motive m
|
||||
|
||||
/-- error: Variable `n` cannot be generalized because the induction principle depends on it -/
|
||||
#guard_msgs in
|
||||
example (n m : Nat) : n = m := by
|
||||
induction m using foo_induct (n := n) generalizing n
|
||||
Loading…
Add table
Reference in a new issue