diff --git a/src/Lean/Meta/Match/MatcherInfo.lean b/src/Lean/Meta/Match/MatcherInfo.lean index 6d9545447c..f3126b96c8 100644 --- a/src/Lean/Meta/Match/MatcherInfo.lean +++ b/src/Lean/Meta/Match/MatcherInfo.lean @@ -29,8 +29,12 @@ def MatcherInfo.numAlts (info : MatcherInfo) : Nat := def MatcherInfo.arity (info : MatcherInfo) : Nat := info.numParams + 1 + info.numDiscrs + info.numAlts +def MatcherInfo.getFirstDiscrPos (info : MatcherInfo) : Nat := + info.numParams + 1 + def MatcherInfo.getMotivePos (info : MatcherInfo) : Nat := info.numParams + namespace Extension structure Entry where @@ -79,15 +83,18 @@ def isMatcherCore (env : Environment) (declName : Name) : Bool := def isMatcher [Monad m] [MonadEnv m] (declName : Name) : m Bool := return isMatcherCore (← getEnv) declName -def isMatcherAppCore (env : Environment) (e : Expr) : Bool := +def isMatcherAppCore? (env : Environment) (e : Expr) : Option MatcherInfo := let fn := e.getAppFn if fn.isConst then if let some matcherInfo := getMatcherInfoCore? env fn.constName! then - e.getAppNumArgs ≥ matcherInfo.arity + if e.getAppNumArgs ≥ matcherInfo.arity then some matcherInfo else none else - false + none else - false + none + +def isMatcherAppCore (env : Environment) (e : Expr) : Bool := + isMatcherAppCore? env e |>.isSome def isMatcherApp [Monad m] [MonadEnv m] (e : Expr) : m Bool := return isMatcherAppCore (← getEnv) e diff --git a/src/Lean/Meta/Tactic/Split.lean b/src/Lean/Meta/Tactic/Split.lean index 034fb7eee6..357c36dacf 100644 --- a/src/Lean/Meta/Tactic/Split.lean +++ b/src/Lean/Meta/Tactic/Split.lean @@ -100,7 +100,7 @@ def splitMatch (mvarId : MVarId) (e : Expr) : MetaM (List MVarId) := do /-- Return an `if-then-else` or `match-expr` to split. -/ partial def findSplit? (env : Environment) (e : Expr) : Option Expr := - if let some target := e.find? fun e => !e.hasLooseBVars && (e.isIte || e.isDIte || isMatcherAppCore env e) then + if let some target := e.find? isCandidate then if e.isIte || e.isDIte then let cond := target.getArg! 1 5 -- Try to find a nested `if` in `cond` @@ -109,6 +109,18 @@ partial def findSplit? (env : Environment) (e : Expr) : Option Expr := some target else none +where + isCandidate (e : Expr) : Bool := do + if e.isIte || e.isDIte then + !(e.getArg! 1 5).hasLooseBVars + else if let some info := isMatcherAppCore? env e then + let args := e.getAppArgs + for i in [info.getFirstDiscrPos : info.getFirstDiscrPos + info.numDiscrs] do + if args[i].hasLooseBVars then + return false + return true + else + false end Split @@ -121,6 +133,7 @@ def splitTarget? (mvarId : MVarId) : MetaM (Option (List MVarId)) := commitWhenS else splitMatch mvarId e else + trace[Meta.Tactic.split] "did not find term to split\n{MessageData.ofGoal mvarId}" return none def splitLocalDecl? (mvarId : MVarId) (fvarId : FVarId) : MetaM (Option (List MVarId)) := commitWhenSome? do @@ -137,4 +150,6 @@ def splitLocalDecl? (mvarId : MVarId) (fvarId : FVarId) : MetaM (Option (List MV else return none +builtin_initialize registerTraceClass `Meta.Tactic.split + end Lean.Meta diff --git a/src/Lean/Meta/Tactic/SplitIf.lean b/src/Lean/Meta/Tactic/SplitIf.lean index 1f8d13dee2..c0bd689707 100644 --- a/src/Lean/Meta/Tactic/SplitIf.lean +++ b/src/Lean/Meta/Tactic/SplitIf.lean @@ -63,7 +63,7 @@ def discharge? (useDecide := false) : Simp.Discharge := fun prop => do /-- Return the condition of an `if` expression to case split. -/ partial def findIfToSplit? (e : Expr) : Option Expr := - if let some iteApp := e.find? fun e => !e.hasLooseBVars && (e.isIte || e.isDIte) then + if let some iteApp := e.find? fun e => (e.isIte || e.isDIte) && !(e.getArg! 1 5).hasLooseBVars then let cond := iteApp.getArg! 1 5 -- Try to find a nested `if` in `cond` findIfToSplit? cond |>.getD cond