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

Lake update across lake versions #2582

Closed
1 task done
PatrickMassot opened this issue Sep 25, 2023 · 4 comments · Fixed by #5684
Closed
1 task done

Lake update across lake versions #2582

PatrickMassot opened this issue Sep 25, 2023 · 4 comments · Fixed by #5684
Labels
enhancement New feature or request Lake Lake related issue

Comments

@PatrickMassot
Copy link
Contributor

Prerequisites

  • Put an X between the brackets on this line if you have done all of the following:
    • Check that your issue is not already filed.
    • Reduce the issue to a minimal, self-contained, reproducible test case. Avoid dependencies to mathlib4 or std4.

Description

Running lake update in an old project lead to errors because it tries to use and old version of lake to handle the modern lakefiles of dependencies.

Context

This happens if you run lake update in a project that depend on Mathlib and is old enough to not know about weakLeanArgs.

Steps to Reproduce

  1. Create directory foo containing the lakefile

    import Lake
    open Lake DSL
    
    package «foo» {
      -- add any package configuration options here
    }
    
    require mathlib from git
      "https://github.com/leanprover-community/mathlib4.git"
    
    @[default_target]
    lean_lib «Foo» {
      -- add any library configuration options here
    }
    

    and the lean-toolchain file containing leanprover/lean4:nightly-2023-06-20

  2. run lake update

Expected behavior: [Clear and concise description of what you expect to happen]

I expect lake to clone a recent version of mathlib without any error message.

Actual behavior: [Clear and concise description of what actually happens]

Get messages:

cloning https://github.com/leanprover-community/mathlib4.git to lake-packages/mathlib
error: ./lake-packages/mathlib/lakefile.lean:31:2: error: 'weakLeanArgs' is not a field of structure 'Lake.LeanLibConfig'
error: ./lake-packages/mathlib/lakefile.lean:55:2: error: 'weakLeanArgs' is not a field of structure 'Lake.LeanLibConfig'
error: ./lake-packages/mathlib/lakefile.lean: package configuration has errors

Versions

Lean (version 4.0.0-nightly-2023-06-20, commit a44dd71, Release) on Ubuntu 22.04

I guess this cannot be fixed in old lake of course, but it would be nice to act now so that future lake won't break like this.

@PatrickMassot PatrickMassot added the bug Something isn't working label Sep 25, 2023
@tydeu tydeu added the Lake Lake related issue label Sep 25, 2023
@tydeu
Copy link
Member

tydeu commented Sep 25, 2023

I think this connects with #2752. Lake should check toolchain versions and compare with its own. If its toolchain is older than the packages it downloads it should error / warn cleanly about that.

@tydeu
Copy link
Member

tydeu commented Oct 12, 2023

Reviewing this again, I noticed that the issue's expected behavior is for this to "just work" and my previous suggestion would still error (just in a different way). It is not clear to me how this could generally "just work". There are some major concerns:

  1. Updating the Lean toolchain: If the Lake version is to old, we need update the toolchain, and as RFC: lake update should update the lean-toolchain #2752 notes, there will not always be a good toolchain. Even in the context of mathlib it is possible for downstream projects to depend both on mathlib and some other project whose newest toolchains are incompatible (e.g., a project may want mathlib and LeanInfer and mathlib master may be on a newer toolchain than LeanInfer supports). In such a case, an error would be necessary as far as I can tell.

  2. Update requires loading the configuration: When an updating a package, even with all needed static information contained in the manifest (which may itself produce errors with incompatible manifests), Lake still needs the dynamic information from the elaborated configuration. This is required to evaluate conditions for conditional dependencies like doc-gen4 and run update hooks like feat: lake: postUpdate? + test #2603 that may even be useful to mathlib. Since such things may effect dependency resolution, they also effect what toolchain is the best to update to. If the configuration is too new, it cannot be evaluated to further resolve dependencies and discover which is the toolchain is needed to fix the errors. One potential approach is to automatically bump the Lean toolchain and try again and then repeat this process for as many bumps as necessary. However, this still has the following problem.

  3. Updating the Lean toolchain can break the root package: If Lake decides to auto-update itself to update upstream dependencies, this can into lead to a Lake that is too new to support the root package's current configuration. If this happens, then every other lake command will break until the updated toolchain is reverted (including all interactive editor features), which seems quite risky.

These problems make it seem very difficult to generally auto-resolve problems caused by incompatible Lake versions. That is why I suggested the above solution were Lake simply cleanly errors if the toolchain is incompatible. However, it is entirely possible I am simply being too pessimistic here and there is a nice solution that would work in most cases and could be recovered from in the edge cases, but I do not yet see it. Any suggestions on what should be done here technically?

@digama0
Copy link
Collaborator

digama0 commented Oct 12, 2023

A simple solution to (1) is to have the user specify that they want to track the lean-toolchain of a dependency (like mathlib). If it errors then so be it, but this is a 90% solution that is clearly actionable by the user if anything goes wrong. (You can give a warning if you detect an incompatibility, but IIUC there isn't really any way to determine whether toolchains are "incompatible" without just trying it and seeing what works.)

@tydeu
Copy link
Member

tydeu commented Oct 12, 2023

@digama0

A simple solution to (1) is to have the user specify that they want to track the lean-toolchain of a dependency (like mathlib). If it errors then so be it.

I agree that this is good solution assuming "if it errors then so be it" is acceptable.

One remaining technically difficult is restarting Lake from within Lake to continue with the update while preserving some of the configuration but not the toolchain. That is, once the first lake update updates the toolchain, it would need to start a second lake update on the toolchain to successfully elaborate the file and that lake update needs to be configured in approximately the same way minus the toolchain. This is doable, but can be quite finicky (just like the passing of arguments from lean --server to lean --worker can be finicky). This finickiness is one of the reasons I originally shied away from this kind of feature, but if it is in high demand it is likely worth it.

@tydeu tydeu added enhancement New feature or request and removed bug Something isn't working labels Oct 12, 2023
github-merge-queue bot pushed a commit that referenced this issue Nov 4, 2024
Lake will now update a package's `lean-toolchain` file on `lake update`
if it finds the package's direct dependencies use a newer compatible
toolchain. To skip this step, use the `--keep-toolchain` CLI option.

Closes #2582. Closes #2752. Closes #5615.

### Toolchain update details

To determine "newest compatible" toolchain, Lake parses the toolchain
listed in the packages' `lean-toolchain` files into four categories:
release , nightly, PR, and other. For newness, release toolchains are
compared by semantic version (e.g., `"v4.4.0" < "v4.8.0"` and
`"v4.6.0-rc1" < "v4.6.0"`) and nightlies are compared by date (e.g.,
`"nightly-2024-01-10" < "nightly-2014-10-01"`). All other toolchain
types and mixtures are incompatible. If there is not a single newest
toolchain, Lake will print a warning and continue updating without
changing the toolchain.

If Lake does find a new toolchain, Lake updates the workspace's
`lean-toolchain` file accordingly and restarts the update process on the
new Lake. If Elan is detected, it will spawn the new Lake process via
`elan run` with the same arguments Lake was initially run with. If Elan
is missing, it will prompt the user to restart Lake manually and exit
with a special error code (4).

### Other changes

To implement this new logic, various other refactors were needed. Here
are some key highlights:

* Logs emitted during package and workspace loading are now eagerly
printed.
* The Elan executable used by Lake is now configurable by the `ELAN`
environment variable.
* The `--lean` CLI option was removed. Use the `LEAN` environment
variable instead.
* `Package.deps` / `Package.opaqueDeps` have been removed. Use
`findPackage?` with a dependency's name instead.
* The dependency resolver now uses a pure breadth-first traversal to
resolve dependencies. It also resolves dependencies in reverse order,
which is done for consistency with targets. Latter targets shadow
earlier ones and latter dependencies take precedence over earlier ones.
**These changes mean the order of dependencies in a Lake manifest will
change after the first `lake update` on this version of Lake.**
JovanGerb pushed a commit to JovanGerb/lean4 that referenced this issue Nov 4, 2024
Lake will now update a package's `lean-toolchain` file on `lake update`
if it finds the package's direct dependencies use a newer compatible
toolchain. To skip this step, use the `--keep-toolchain` CLI option.

Closes leanprover#2582. Closes leanprover#2752. Closes leanprover#5615.

### Toolchain update details

To determine "newest compatible" toolchain, Lake parses the toolchain
listed in the packages' `lean-toolchain` files into four categories:
release , nightly, PR, and other. For newness, release toolchains are
compared by semantic version (e.g., `"v4.4.0" < "v4.8.0"` and
`"v4.6.0-rc1" < "v4.6.0"`) and nightlies are compared by date (e.g.,
`"nightly-2024-01-10" < "nightly-2014-10-01"`). All other toolchain
types and mixtures are incompatible. If there is not a single newest
toolchain, Lake will print a warning and continue updating without
changing the toolchain.

If Lake does find a new toolchain, Lake updates the workspace's
`lean-toolchain` file accordingly and restarts the update process on the
new Lake. If Elan is detected, it will spawn the new Lake process via
`elan run` with the same arguments Lake was initially run with. If Elan
is missing, it will prompt the user to restart Lake manually and exit
with a special error code (4).

### Other changes

To implement this new logic, various other refactors were needed. Here
are some key highlights:

* Logs emitted during package and workspace loading are now eagerly
printed.
* The Elan executable used by Lake is now configurable by the `ELAN`
environment variable.
* The `--lean` CLI option was removed. Use the `LEAN` environment
variable instead.
* `Package.deps` / `Package.opaqueDeps` have been removed. Use
`findPackage?` with a dependency's name instead.
* The dependency resolver now uses a pure breadth-first traversal to
resolve dependencies. It also resolves dependencies in reverse order,
which is done for consistency with targets. Latter targets shadow
earlier ones and latter dependencies take precedence over earlier ones.
**These changes mean the order of dependencies in a Lake manifest will
change after the first `lake update` on this version of Lake.**
kim-em pushed a commit that referenced this issue Nov 29, 2024
Lake will now update a package's `lean-toolchain` file on `lake update`
if it finds the package's direct dependencies use a newer compatible
toolchain. To skip this step, use the `--keep-toolchain` CLI option.

Closes #2582. Closes #2752. Closes #5615.

To determine "newest compatible" toolchain, Lake parses the toolchain
listed in the packages' `lean-toolchain` files into four categories:
release , nightly, PR, and other. For newness, release toolchains are
compared by semantic version (e.g., `"v4.4.0" < "v4.8.0"` and
`"v4.6.0-rc1" < "v4.6.0"`) and nightlies are compared by date (e.g.,
`"nightly-2024-01-10" < "nightly-2014-10-01"`). All other toolchain
types and mixtures are incompatible. If there is not a single newest
toolchain, Lake will print a warning and continue updating without
changing the toolchain.

If Lake does find a new toolchain, Lake updates the workspace's
`lean-toolchain` file accordingly and restarts the update process on the
new Lake. If Elan is detected, it will spawn the new Lake process via
`elan run` with the same arguments Lake was initially run with. If Elan
is missing, it will prompt the user to restart Lake manually and exit
with a special error code (4).

To implement this new logic, various other refactors were needed. Here
are some key highlights:

* Logs emitted during package and workspace loading are now eagerly
printed.
* The Elan executable used by Lake is now configurable by the `ELAN`
environment variable.
* The `--lean` CLI option was removed. Use the `LEAN` environment
variable instead.
* `Package.deps` / `Package.opaqueDeps` have been removed. Use
`findPackage?` with a dependency's name instead.
* The dependency resolver now uses a pure breadth-first traversal to
resolve dependencies. It also resolves dependencies in reverse order,
which is done for consistency with targets. Latter targets shadow
earlier ones and latter dependencies take precedence over earlier ones.
**These changes mean the order of dependencies in a Lake manifest will
change after the first `lake update` on this version of Lake.**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Lake Lake related issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants