-
Notifications
You must be signed in to change notification settings - Fork 444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: syntax and delaborator for delayed assignment metavariables #3494
Conversation
Mathlib CI status (docs):
|
Will we be able to limit the scope of the metavariable in this way? e.g. |
@ericrbg-harmonic It lets you write |
I am concerned about the size of this expression, as I often see these metavariables in printouts and I generally don't actually care about the values of the arguments and only the fact that it is a metavariable (possibly an unassignable metavariable) is relevant to me. Maybe |
195ce1c
to
7b90837
Compare
7b90837
to
c4ee28d
Compare
32d60c5
to
696f70b
Compare
Where before we had ```lean #check fun x : Nat => ?a -- fun x ↦ ?m.7 x : (x : Nat) → ?m.6 x ``` Now by default we have ```lean #check fun x : Nat => ?a -- fun x => ?a : (x : Nat) → ?m.6 x ``` in particular, delayed assignment metavariables such as `?m.7` pretty print using the name of the metavariable they are delayed assigned to, suppressing the arguments used in the delayed assignment (hence `?a` rather than `?a x`). Hovering over `?a` shows `?m.7 x`. The benefit is that users can see the user-provided name in local contexts. The original pretty printing behavior can be recovered using `set_option pp.mvars.delayed true`. This PR also extends the documentation for holes and synthetic holes, with useful high-level technical details about what delayed assignments are. (This PR supercedes leanprover#3494, which has a round-trippable notation for delayed assignments. The notation in this PR is unlikely to round trip, but it is better than the current situation, where delayed assignment metavariables never round trip.)
Where before we had ```lean #check fun x : Nat => ?a -- fun x ↦ ?m.7 x : (x : Nat) → ?m.6 x ``` Now by default we have ```lean #check fun x : Nat => ?a -- fun x => ?a : (x : Nat) → ?m.6 x ``` In particular, delayed assignment metavariables such as `?m.7` pretty print using the name of the metavariable they are delayed assigned to, suppressing the bound variables used in the delayed assignment (hence `?a` rather than `?a x`). Hovering over `?a` shows `?m.7 x`. The benefit is that users can see the user-provided name in local contexts. A justification for this pretty printing choice is that `?m.7 x` is supposed to stand for `?a`, and furthermore it is just as opaque to assignment in defeq as `?a` is (however, when synthetic opaque metavariables are made assignable, delayed assignments can be a little less assignable than true synthetic opaque metavariables). The original pretty printing behavior can be recovered using `set_option pp.mvars.delayed true`. This PR also extends the documentation for holes and synthetic holes, with some technical details about what delayed assignments are. This likely should be moved to the reference manual, but for now it is included in this docstring. (This PR is a simplified version of #3494, which has a round-trippable notation for delayed assignments. The pretty printing in this PR is unlikely to round trip, but it is better than the current situation, which is that delayed assignment metavariables never round trip, and plus it does not require introducing a new notation.)
It's often confusing how
fun x y => ?foo
elaborates asfun x y => ?m.123 x y
, with no way to see how?m.123
is connected to?foo
. This PR adds syntax for delayed assignment metavariables, where the elaborated result pretty prints asfun x y => ?foo(x, y)
instead. Hovering over the expression still shows the underlying?m.123 x y
term, and hovering overfoo
shows whateverfoo
might be currently assigned to, if anything. The syntax can be turned off withset_option pp.mvars.delayed false
.This also adds an elaborator for
?foo(x := a, y := b)
syntax to create a new delayed assignment metavariable from a metavariable, making the pretty printed syntax elaboratable. In addition to being for making pretty printing round trip, it is filling in a missing feature, since, as a user, it's impossible to use synthetic holes in incompatible local contexts without being able to specify delayed assignments. For example, with the?foo
above we can then later refer tofun x y => ?foo(x, y)
(where?foo(x, y)
is short for?foo(x := x, y := y)
), even though thex
andy
binders are totally new fvars.The syntax is chosen to (1) use parentheses with no whitespace since that is reserved for new syntax, (2) to resemble structure instance notation, and (3) to be something like the Lean version of lambda calculus substitution (and in any case, square brackets are already used by GetElem).