/- Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude import Lean.Meta.CollectFVars import Lean.Meta.Tactic.Clear namespace Lean.Meta private partial def cleanupCore (mvarId : MVarId) (toPreserve : Array FVarId) (indirectProps : Bool) : MetaM MVarId := do mvarId.withContext do mvarId.checkNotAssigned `cleanup let used ← collectUsed |>.run' (false, {}) let mut lctx ← getLCtx for localDecl in lctx do unless used.contains localDecl.fvarId do lctx := lctx.erase localDecl.fvarId let localInsts := (← getLocalInstances).filter fun inst => used.contains inst.fvar.fvarId! let mvarNew ← mkFreshExprMVarAt lctx localInsts (← instantiateMVars (← mvarId.getType)) .syntheticOpaque (← mvarId.getTag) mvarId.assign mvarNew return mvarNew.mvarId! where addUsedFVars (e : Expr) : StateRefT (Bool × FVarIdSet) MetaM Unit := do let (_, s) ← (← instantiateMVars e).collectFVars |>.run {} for fvarId in s.fvarSet do addUsedFVar fvarId addDeps (fvarId : FVarId) : StateRefT (Bool × FVarIdSet) MetaM Unit := do let localDecl ← fvarId.getDecl addUsedFVars localDecl.type if let some val := localDecl.value? then addUsedFVars val addUsedFVar (fvarId : FVarId) : StateRefT (Bool × FVarIdSet) MetaM Unit := do unless (← get).2.contains fvarId do modify fun (_, s) => (true, s.insert fvarId) addDeps fvarId /-- We include `p` in the used-set, if `p` is a proposition that contains a `x` that is in the used-set. -/ collectPropsStep : StateRefT (Bool × FVarIdSet) MetaM Unit := do let usedSet := (← get).2 for localDecl in (← getLCtx) do if (← isProp localDecl.type) then if (← dependsOnPred localDecl.type usedSet.contains) then addUsedFVar localDecl.fvarId collectProps : StateRefT (Bool × FVarIdSet) MetaM Unit := do modify fun s => (false, s.2) collectPropsStep if (← get).1 then collectProps collectUsed : StateRefT (Bool × FVarIdSet) MetaM FVarIdSet := do addUsedFVars (← instantiateMVars (← mvarId.getType)) toPreserve.forM addUsedFVar if indirectProps then collectProps return (← get).2 /-- Auxiliary tactic for cleaning the local context. It removes local declarations (aka hypotheses) that are *not* relevant. We say a variable `x` is "relevant" if - It occurs in the `toPreserve` array, or - It occurs in the target type, or - There is a relevant variable `y` that depends on `x`, or - If `indirectProps` is true, the type of `x` is a proposition and it depends on a relevant variable `y`. By default, `toPreserve := #[]` and `indirectProps := true`. These settings are used in the mathlib tactic `extract_goal` to give the user more control over which variables to include. -/ abbrev _root_.Lean.MVarId.cleanup (mvarId : MVarId) (toPreserve : Array FVarId := #[]) (indirectProps : Bool := true) : MetaM MVarId := do cleanupCore mvarId toPreserve indirectProps @[deprecated MVarId.cleanup] abbrev cleanup (mvarId : MVarId) : MetaM MVarId := do mvarId.cleanup end Lean.Meta