-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
move to a simpler versioning policy for the Compiler.jl stdlib #57520
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
Conversation
aed9ca0
to
2dba32d
Compare
@Keno Any input here? This sounds like a sensible solution to me, up to how we might choose to do patch versioning. At least until the Compiler interfaces start to stabilize enough that we are semi-frequently making one-sided changes, I don't think we'll get a ton of value out of different versioning. |
I've thought about this some more, and I generally with the direction. I think it makes sense for downstream users of the compiler to register themselves with both versions of the compiler. Additionally, they should probably follow the base mechanism for deciding which copy of the compiler to use. I guess the one thing that I'm still not entirely clear about is how to do the versioning itself. In particular, if one of the versions of the compiler is the base copy, then we already need to deal with the fact that they are implicitly versioned by base commit. My proposal would thus be that - for the time being, we don't actually release any formal new Compiler.jl versions and just rely on base version numbers. In the future, I could see us moving Compiler.jl out of Julia, in which case, we can tag version numbers whenever we bump the Compiler.jl version in Julia base (like we do JuliaSyntax right now), but I think that would depend on some additional decoupling. Lastly, I think we probably need to provide some utility interfaces in the Compiler code that makes it easy for downstream packages to do this split version thing. |
So, basically, we're going ahead with the approach I outlined before, but, for how to actually use the Compiler stdlib in a package, we'll use a mechanism similar to |
It still needs the extension so that the code is available if someone asks for it even if not enabled by default. |
I am not sure this design works well in practice when downstream users rely on interfaces defined in a parent package such as Cthulhu. Current designWhen a Compiler stdlib is loaded, there are two concurrent Compiler modules, each defining their own types and functions. The solution proposed by @aviatesk works around this by duplicating the contents of a package in an extension that uses symbols from the Compiler stdlib. High-level package entry points (such as IssueThis design works well for these specific entry points, because the user will not observe any changes, but there are a few issues when trying to apply this downstream. I will take the example of Cthulhu and Diffractor (downstream user of Cthulhu), though the following applies to any such pattern. Cthulhu now has two modules: one that works with Here are workarounds that I have attempted, and that failed (a few reasons were already mentioned above):
I believe there are ways to re-architect a package so that it provides support for both Compiler packages with the current extension mechanism (such as replacing subtyping with trait-based dispatch in its interface), but not without significantly intrusive changes which I would perceive as undesirable. |
One possible solution could be to do the same thing as the Cthulhu.jl: CTHULHU_MODULE = IdDict{Module, Module}(Base.Compiler => Cthulhu)
function duplicate_package(Compiler)
mod = @eval module CthulhuCompilerRuntimeExt
const CC = $Compiler
using .CC
include("CthulhuBase.jl")
end
CTHULHU_MODULE[Compiler] = mod
end
function __init__()
register_compiler_hook(duplicate_package, @__MODULE__)
end Diffractor.jl: DIFFRACTOR_MODULE = IdDict{Module, Module}(Base.Compiler => Diffractor)
function duplicate_package(Compiler)
mod = @eval module DiffractorCompilerRuntimeExt
const CC = $Compiler
using .CC
const Cthulhu = Cthulhu.CTHULHU_MODULE[CC]
using .Cthulhu
include("DiffractorBase.jl")
end
DIFFRACTOR_MODULE[Compiler] = mod
end
function __init__()
register_compiler_hook(duplicate_package, @__MODULE__)
end This wouldn't benefit from precompilation, nor support any kind of versioning/compat, and yet again relies on |
Another path worth mentioning would be to go back to managing a single This could be expressed as a special [sources]
Compiler = {path = "@julia/Compiler"} I personally find that simpler and clearer than any of the other solutions that try to support two different |
It's been a little while, but I'd like to get this PR moving forward again. The problem with the current package extension approach is that packages need to provide two essentially duplicate code paths depending on the Compiler implementation. Instead, I thought about a way to switch compiler implementations within the Compiler stdlib itself: as an alternative, what about the idea of having a package that's essentially identical to baremodule Compiler
for name in Base.names(Base.Compiler; all=true, imported=true)
Core.eval(Compiler, :(using Base.Compiler: $name))
end
end Specifically, we could register v0.0.0 of the Compiler stdlib with the fallback implementation. This version would just import everything from To implement this, we could yank all currently released versions of Compiler.jl and, for now, release only this v0.0.0 fallback version as described. Then packages can declare
Compiler = "0" By default, this would just let them use names from pkg> dev path/to/Compiler.jl or pkg> add https://github.com/JuliaLang/julia/tree/avi/EA-overhaul/Compiler Of course, when we eventually start proper versioning for the Compiler.jl stdlib, packages using this setup could easily migrate just by changing their Compiler version requirement (It might even be useful to keep this v0.0.0 ( |
2dba32d
to
98d5ac9
Compare
98d5ac9
to
11aaf65
Compare
I've implemented the fallback version for the Compiler.jl stdlib, as proposed in the previous comment. There are a couple of things we should probably discuss or note:
|
If we agree on this approach, here's how we'll finish switching to the new Compiler.jl stdlib infrastructure:
|
Yanking is kind of problematic. Is there a chance that people are using these?
That's not a good version number to use for any release... |
A quick package search reveals that no registered package uses Compiler in their project, so yanking should be safe. EDIT: I wonder why Diffractor.jl does not show up in that search. Is it scoped to releases only? (Diffractor hasn't released after it added its dependency to Compiler in its project) |
I agree, but this Compiler stdlib version is special. It's a temporary fallback version we'll use until we start proper versioning for the Compiler stdlib. So, I think using this unusual version number 0.0.0 might be a good way to show that it's a special version. |
11aaf65
to
d3d1ddd
Compare
The `Compiler.jl` implementation added by this commit is not bootstrappable and is solely intended to be registered in the Julia package registry. For details on the design and usage of this Compiler standard library, please refer to the included docstring.
d3d1ddd
to
a8f3e4d
Compare
I’ve completed the process proposed at #57520 (comment). As a result, this PR only makes minor adjustments to Compiler/Project.toml and adds a Compiler/README. If you have any feedbacks about the README added in this PR or about the README in the BaseCompiler.jl repository, please let me know. |
This commit adjusts /Compiler/Project.toml and adds a new /Compiler/README.md based on the new versioning policy for the Compiler.jl stdlib. Regarding the new versioning policy and the latest way to use the Compiler.jl stdlib, please refer to this comment[^1] and the newly added READMEs (`JuliaLang/julia/Compiler/README.md`[^2] and and `JuliaLang/BaseCompiler.jl/README.md`[^3]). [^1]: #57520 (comment) [^2]: https://github.com/JuliaLang/julia/blob/a8f3e4d0603692ac79700890d3e8d35e904e000e/Compiler/README.md [^3]: https://github.com/JuliaLang/BaseCompiler.jl
…Lang#57520) This commit adjusts /Compiler/Project.toml and adds a new /Compiler/README.md based on the new versioning policy for the Compiler.jl stdlib. Regarding the new versioning policy and the latest way to use the Compiler.jl stdlib, please refer to this comment[^1] and the newly added READMEs (`JuliaLang/julia/Compiler/README.md`[^2] and and `JuliaLang/BaseCompiler.jl/README.md`[^3]). [^1]: JuliaLang#57520 (comment) [^2]: https://github.com/JuliaLang/julia/blob/a8f3e4d0603692ac79700890d3e8d35e904e000e/Compiler/README.md [^3]: https://github.com/JuliaLang/BaseCompiler.jl
…Lang#57520) This commit adjusts /Compiler/Project.toml and adds a new /Compiler/README.md based on the new versioning policy for the Compiler.jl stdlib. Regarding the new versioning policy and the latest way to use the Compiler.jl stdlib, please refer to this comment[^1] and the newly added READMEs (`JuliaLang/julia/Compiler/README.md`[^2] and and `JuliaLang/BaseCompiler.jl/README.md`[^3]). [^1]: JuliaLang#57520 (comment) [^2]: https://github.com/JuliaLang/julia/blob/a8f3e4d0603692ac79700890d3e8d35e904e000e/Compiler/README.md [^3]: https://github.com/JuliaLang/BaseCompiler.jl
This commit adjusts /Compiler/Project.toml and adds a new /Compiler/README.md based on the new versioning policy for the Compiler.jl stdlib. Regarding the new versioning policy and the latest way to use the Compiler.jl stdlib, please refer to this comment[^1] and the newly added READMEs (`JuliaLang/julia/Compiler/README.md`[^2] and and `JuliaLang/BaseCompiler.jl/README.md`[^3]). [^1]: #57520 (comment) [^2]: https://github.com/JuliaLang/julia/blob/a8f3e4d0603692ac79700890d3e8d35e904e000e/Compiler/README.md [^3]: https://github.com/JuliaLang/BaseCompiler.jl
Update (May 06, 2025)
As a result of discussions, the versioning and management policy for the Compiler.jl stdlib ended up being slightly different from what was originally proposed. For details, please refer to this comment and the newly added READMEs (JuliaLang/julia/Compiler/README.md and JuliaLang/BaseCompiler.jl/README.md).
Original OP
For external packages like Cthulhu that use the Compiler.jl stdlib, it's quite a hassle to manage all three types of compatibility: between the external package, the Julia runtime, and Compiler.jl.
I'm thinking instead of handling these compatibility issues by some complex version engineering for Compiler.jl, we should keep its use supplementary. External
AbstractInterpreter
packages should primarily useBase.Compiler
, while managing compatibility with the Julia runtime andBase.Compiler
. This would bring us back to the previous situation, but it seems better in terms of compatibility management.On the other hand, using the Compiler.jl stdlib allows for easy switching of the
Compiler
implementation, which should be an optional benefit. This is especially useful when developing theCompiler
itself, where it's common to dopkg> dev /path/to/Compiler
. In such cases, the implementation of the Compiler.jl stdlib should be used instead ofBase.Compiler
.As a mechanism to switch the
Compiler
implementation used by externalAbstractInterpreter
packages, using package extensions might be the simplest approach. As shown inthis example PR, we can switch the
Compiler
implementation whenusing Compiler
is called1, and still precompile the usual code. However, to list Compiler.jl in[extensions]
, it needs a version. To this end, I propose releasing Compiler.jl versions in line with the Julia runtime versions, following other Julia standard libraries. But we would only do minor version releases, not patch releases, which are harder to define. Specifically, we could release a corresponding version of Compiler.jl when a release branch is cut. After that, we wouldn't manage patch versions, and as long aspkg> dev /path/to/Compiler
works, this simple versioning should suffice.Alternatively, we could register a single version
1.0.0
of Compiler.jl with a dummy implementation, letting the external package determine if the implementation is real (developed) or dummy, but this seems more hacky than using package extensions.Footnotes
Also, I'm aware of another issue: when using the Compiler.jl
stdlib, you need to run
InteractiveUtils.@activate Compiler
first,or else some reflection utilities won't work (for example,
Base._which(tt; method_table=Compiler.method_table(myinterp))
).I think this problem can be solved by adding
InteractiveUtils.@activate
in the__init__
function of the packageextension code, but I'm not sure if this is a safe solution. It might
be better to set up a callback that only gets called when
InteractiveUtils.@activate
is executed? ↩