Skip to content
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: Upstream derive handler for ToExpr from Mathlib #5906

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

alexkeizer
Copy link
Contributor

@alexkeizer alexkeizer commented Oct 31, 2024

This takes the derive handler for ToExpr from mathlib, and upstreams it into core.

The derive handler uses an auxiliary typeclass, ToLevel to ensure the derived ToExpr instances are properly universe polymorphic (when the original type is polymorphic), so we upstream this, too.

/-- A class to create `Level` expressions that denote particular universe levels in Lean.
`Lean.ToLevel.toLevel.{u}` evaluates to a `Lean.Level` term representing `u` -/
class ToLevel.{u} where
  /-- A `Level` that represents the universe level `u`. -/
  toLevel : Level
  /-- The universe itself. This is only here to avoid the "unused universe parameter" error. -/
  univ : Type u := Sort u

Credit goes to @kmill for originally developing the derive handler. We'll use this in a light-weight, basic QQ alternative that currently lives in a PR to LNSym, but we plan to upstream also.

@kmill
Copy link
Collaborator

kmill commented Oct 31, 2024

Thanks for your interest Alex — upstreaming this has been on my radar for awhile, especially since #expr now uses ToExpr instances. However, for upstreaming, please be sure to run your plans by core developers ahead of time. It's still not clear how this ToExpr deriving handler will appear in core, and it has some issues that will likely need more core fixes (for example, ToLevel should not need to live in a universe above Type, yet it does).

@alexkeizer
Copy link
Contributor Author

Thanks for your input, Kyle. For the record, I did mention, quite a while back, on the Zulip that I'd like to have ToExpr available in core, and got as response that this seemed like a good idea. Admittedly, I didn't follow up on that saying I would do it (since I wasn't planning to at the time), but recently figured I might as well get that ball rolling myself. I'll communicate this more clearly in the future.

@alexkeizer
Copy link
Contributor Author

alexkeizer commented Oct 31, 2024

I've opened an issue to track the discussion at #5909

@kmill
Copy link
Collaborator

kmill commented Nov 8, 2024

Great, the ToExpr RFC was just accepted — looking forward to seeing progress on this!

@alexkeizer
Copy link
Contributor Author

Wonderful! I'm currently on vacation, but will push this forward when I'm back on the 25th!

By the way, where did this acceptance happen? I didn't see any activity on the issue.

@kmill
Copy link
Collaborator

kmill commented Nov 10, 2024

It looks like there's a gap in FRO communication here — the triage team accepted it on Thursday and assigned to me seeing that it gets implemented.

I'd suggest that we do two PRs here. One would be adding ToLevel and fixing all the currently existing ToExpr handlers, and then the second would be this PR, upstreaming the ToExpr handler. Does that sound reasonable? (No need to respond until you get back!)

@alexkeizer
Copy link
Contributor Author

alexkeizer commented Nov 27, 2024

@kmill Thanks for clarifying. Splitting it into 2 PRs makes sense to me!

For the first PR, should I upstream the ToLevel class as-is, or should I use the alternative definition I proposed in #5909 to avoid the universe bump?

@kmill
Copy link
Collaborator

kmill commented Nov 29, 2024

We should use the improved ToLevel since we definitely don't want the universe bump.

@alexkeizer
Copy link
Contributor Author

I've opened a PR to upstream ToLevel at #6285

github-merge-queue bot pushed a commit that referenced this pull request Dec 5, 2024
This PR upstreams the `ToLevel` typeclass from mathlib and uses it to
fix the existing `ToExpr` instances so that they are truly universe
polymorphic (previously it generated malformed expressions when the
universe level was nonzero). We improve on the mathlib definition of
`ToLevel` to ensure the class always lives in `Type`, irrespective of
the universe parameter.

This implements part one of the plan to upstream a derive handler for
`ToExpr`, as discussed in #5906 and #5909.

---------

Co-authored-by: Kyle Miller <[email protected]>
Co-authored-by: Tobias Grosser <[email protected]>
toExpr := $(mkIdent auxFunName).{$levels,*}
toTypeExpr := $toTypeExpr)
instances := instances.push instCmd
return instances
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a sort-of-bug that would be nice to fix. If you use these deriving handlers with set_option autoImplicit false, then the universe level variables cause errors.

Ideally we would use $(...):ident.{$levels,*} on this instance to insert levels, but that would prevent the automatic instance name generator from being used.

Alternatively, we could wrap the instance in three commands: section, universe $levels*, and end.

Would you mind adding a test that the deriving handler works when autoImplicit is false as well? (Take a look at lean/run/partialDelta.lean for an example of how test files are structured.)

Copy link
Contributor Author

@alexkeizer alexkeizer Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "bug" is actually slightly trickier than that still: things also break if we explicitly add a universe u command, even if autoImplicits are enabled.

Alternatively, we could wrap the instance in three commands: section, universe $levels*, and end.

I implemented this, expect using universe $levels* in as an abbreviation for the section stuff.
Then, to prevent universe clashes, I check which universe names have been explicitly added to the Elaboration state, and remove those from the $levels list.

This fixes the tests that use exclusively explicit or implicit universes, but there is a final test that has both that still fails.

EDIT: turns out that failing test had a typo, and was in fact failing because it had an autoImplicit type parameter. I've fixed that typo, and added yet another testcase that tests the autoImplicit type parameter (and is currently still failing).

This also ensures that `mkLet` is resolved to `Lean.Elab.Deriving.mkLet` (as intended) instead of `Lean.mkLet`
The final test case currently fails, exposing a bug when auto implicits are disabled
@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Dec 11, 2024
@leanprover-community-bot
Copy link
Collaborator

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b862e2d25163584322bcca54e5e56d671da1f258 --onto 8709ca35e9ddb977f7d050751e04981e2ab0d5c7. (2024-12-11 15:18:28)

Turns out I had a typo in the argument list. The problem was not with implicit universes, rather it was with implicit parameters.
Also adds new testcases to expose this bug properly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants