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

uparse breaks precompilation #649

Open
amilsted opened this issue May 10, 2023 · 7 comments
Open

uparse breaks precompilation #649

amilsted opened this issue May 10, 2023 · 7 comments

Comments

@amilsted
Copy link

It seems I cannot precompile code that makes use of uparse. In Julia 1.9 I get the error

nested task error: Evaluation into the closed module `Unitful` breaks incremental compilation because the side effects will not be permanent. This is likely due to some other module mutating `Unitful` with `eval` during precompilation - don't do this.
    Stacktrace:
      [1] eval
        @ ./boot.jl:370 [inlined]
      [2] eval
        @ ~/.julia/packages/Unitful/KGZ8U/src/Unitful.jl:1 [inlined]
      [3] uparse(str::String; unit_context::Module)
        @ Unitful ~/.julia/packages/Unitful/KGZ8U/src/user.jl:662
      [4] uparse
        @ ~/.julia/packages/Unitful/KGZ8U/src/user.jl:660 [inlined]

while trying to precompile a package that has code that uses uparse in its @compile_workload block (using PrecompilationTools). The code just calls uparse on a string (no module argument).

@amilsted
Copy link
Author

amilsted commented May 11, 2023

Suggestion (from @ChrisRackauckas on slack, albeit without the Unitful context) to use Symbolics.jl (I guess this?: https://docs.sciml.ai/Symbolics/stable/manual/parsing/) or JuliaInterpreter (perhaps using https://juliadebug.github.io/JuliaInterpreter.jl/stable/dev_reference/#JuliaInterpreter.eval_code ?).

@timholy
Copy link
Contributor

timholy commented May 12, 2023

A MWE would be interesting to see.

@ChrisRackauckas
Copy link
Contributor

I don't remember responding on Slack to anything related to unitful here, just on parsing a Julia expression 😅 . :(2 * x) can be ran by using JuliaInterpreter, or if you have a runtime version of that function you can parse it with Symbolics.jl. I am not sure if that's related to uparse or know what uparse is doing.

@amilsted
Copy link
Author

amilsted commented May 12, 2023

Sorry @ChrisRackauckas, I know I didn't mention Unitful on slack!

The uparse implementation calls eval() on an expression like 100m/s^2, where m and s are usually fields of the Unitful module. There is also support for supplying a user module containing alternative definitions of unit symbols.

@timholy here's an MWE. Try to precompile the following package:

module MyTestPkg

using PrecompileTools
using Unitful: uparse

@compile_workload begin
    uparse("100s")
end

end

You will get:

ERROR: LoadError: Evaluation into the closed module `Unitful` breaks incremental compilation because the side effects will not be permanent. This is likely due to some other module mutating `Unitful` with `eval` during precompilation - don't do this.

Edit: @timholy Just realized you might have meant an MWE of the solution, not the problem...

@amilsted
Copy link
Author

amilsted commented May 12, 2023

This precompiles successfully:

module MyTestPkg

using PrecompileTools
using Symbolics
using Unitful

_my_uparse(s) = Symbolics.parse_expr_to_symbolic(Meta.parse(s), Unitful)

@compile_workload begin
    _my_uparse("100m/s^2")
end

end

Also, _my_uparse() gives correct results as long as the string only involves units defined in Unitful and literal numbers. If we pass the expression through Unitful.lookup_units() first, this ought to be a good solution. Have to branch on whether the output is just a unit, or an expression.

The JuliaInterpreter version is harder for me to figure out.

@amilsted
Copy link
Author

amilsted commented Jun 6, 2023

JuliaInterpreter version:

module MyTestPkg

using PrecompileTools
using JuliaInterpreter
using Unitful

_my_uparse(s) = JuliaInterpreter.finish_and_return!(Frame(Unitful, Meta.parse(s)))

@compile_workload begin
    _my_uparse("100m/s^2")
end

end

@YoungFaithful
Copy link

Hitting the same problem. Would highly appreciate some support 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants