Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: Collect all dependencies required for an expression
Leni Aniva (Aug 25 2025 at 14:01):
Is there a function that collects all fvars that are required for an expression to make sense?
e.g., if I have
b : a
c : b
and the expression is f c, then both b and c would need to exist for this expression to make sense. However, collectFVars only collects c.
Jannis Limperg (Aug 25 2025 at 14:38):
I'm not aware of such a function.
In case it helps, I believe the specific situation you mention is not possible because f cannot be typed without mentioning b (i.e., @f b c), except if f is itself an fvar. Maybe there's an invariant here that can be exploited. Another corner case is unassigned mvars; there you'll have to assume that any fvar mentioned in the mvar's local context could potentially be used.
Kyle Miller (Aug 25 2025 at 14:45):
First thing that comes to mind is that you could add e := f c to the local context then use Lean.Meta.collectForwardDeps on every preexisting local variable. The set of local variables that have e as a forward dependency consist of the minimal context for f c. This handles mvars too.
Leni Aniva (Aug 25 2025 at 15:26):
Jannis Limperg said:
I'm not aware of such a function.
In case it helps, I believe the specific situation you mention is not possible because
fcannot be typed without mentioningb(i.e.,@f b c), except iffis itself an fvar. Maybe there's an invariant here that can be exploited. Another corner case is unassigned mvars; there you'll have to assume that any fvar mentioned in the mvar's local context could potentially be used.
assume f is a constant
Aaron Liu (Aug 25 2025 at 15:40):
def foo (n : Nat) : Type := Nat
example (n : Nat) (m : foo n) : Nat.isValidChar m := by
-- in this context the goal does not mention `n`
-- but the type of `m` depends on `n`
-- `Nat.isValidChar` is a constant
trace_state
sorry
Leni Aniva (Aug 25 2025 at 15:50):
I see what you mean. The example I showed I above is a bad one. This would make more sense:
b : a
c : b
d : a = (some function of c)
and the expr is f d. In this case b and c are also dependencies. Or if the expr is just c, in which case b must also be a dependency.
Aaron Liu (Aug 25 2025 at 15:57):
What is your use case for this function?
Leni Aniva (Aug 25 2025 at 15:57):
Aaron Liu said:
What is your use case for this function?
determine the minimal context for an expression
Aaron Liu (Aug 25 2025 at 16:04):
I found docs#Lean.findExprDependsOn
Aaron Liu (Aug 25 2025 at 16:06):
this would be great if the arguments pf and pm were monadic (but I guess then you wouldn't be able to cache it)
Leni Aniva (Aug 25 2025 at 16:08):
Aaron Liu said:
I found docs#Lean.findExprDependsOn
This doesn't work for the case where the expr is just c
Leni Aniva (Aug 25 2025 at 16:08):
It does not signal that b is a dependency
Aaron Liu (Aug 25 2025 at 16:08):
I found docs#Lean.Expr.getMVarDependencies
Aaron Liu (Aug 25 2025 at 16:08):
it only works for mvar dependencies
Aaron Liu (Aug 25 2025 at 16:12):
You could loop through the local context in reverse and docs#Lean.MVarId.tryClear everything
Kyle Miller (Aug 25 2025 at 16:15):
I'll mention again that you can do Lean.Meta.collectForwardDeps on everything in the local context to figure out the correct dependencies. Adding the expression as a let variable is a trick to then let this computation process all the fvars and metavariables in your expression correctly.
Kyle Miller (Aug 25 2025 at 16:18):
Or there's the weird mkLambdaFVars (<- getLCtx).getFVars e (usedOnly := true), but you'll lose the connection to which fvar was actually used. It probably also needs a step to clear aux decls from the local context first.
Last updated: Dec 20 2025 at 21:32 UTC