Skip to content

juliac crashes with MethodError(f=Base.Enums.namemap, args=(<EnumX type>.T,), world=[...]) #59280

@RomeoV

Description

@RomeoV

Summary

While working on #59215 and SciML/NonlinearSolve.jl#665 one issue keeps reoccurring:

MethodError(f=Base.Enums.namemap, args=(SciMLBase.ReturnCode.T,), world=0x0000000000009661)

In #59215 this already came up (and similarly at JuliaCon) once we moved the init call from compile time to runtime (using OncePerProcess), and now I have taken some time to get to the bottom of it.
I believe there is some issue with [EnumX.jl](https://github.com/fredrikekre/EnumX.jl) and its interplay with trimming (note that ReturnCode is based on EnumX.jl).

I have tried to isolate a minimum failing example, peeling away layers of indirection from init and moving it as much as possible to compile time _prob and _alg). At this point, NonlinearSolve is mostly just setting up caches, and I don't think it should be messing with any enums or world ages still, leading me to believe there may be a bug in the juliac implementation that's triggered here.

module TrimSimpleNonlinearSolve
using NonlinearSolveFirstOrder
using ADTypes: AutoForwardDiff
using LinearSolve: CholeskyFactorization

function f(u, p)
    return (u .- p.λ) .^ 2
end

struct MyParams{T}
    λ::T
end

const autodiff = AutoForwardDiff(; chunksize=1)
const alg = LevenbergMarquardt(; autodiff, linsolve=CholeskyFactorization())
const prob = NonlinearLeastSquaresProblem{false}(f, rand(2), MyParams(rand()))
const _prob = NonlinearSolveFirstOrder.DiffEqBase.get_concrete_problem(prob, false; u0=prob.u0, p=prob.p)
const _alg = NonlinearSolveFirstOrder.DiffEqBase.prepare_alg(alg, _prob.u0, _prob.p, _prob)

function minimize(x)
    # inlined and simplified version of
    # ````
    # cache = init(prob, alg; p=MyParams(x))
    # ````

    # this takes us here: https://github.com/SciML/NonlinearSolve.jl/blob/b37b31b22a6650c773a4fdef8ca220f4e8815051/lib/NonlinearSolveFirstOrder/src/solve.jl#L123-L129
    cache = NonlinearSolveFirstOrder.DiffEqBase.__init(_prob, _alg)

    solve!(cache)
    return cache.u
end
end # module TrimSimpleNonlinearSolve

with main.jl

using TrimSimpleNonlinearSolve

function @main(argv::Vector{String})::Cint
    λ = try  # currently calling from `julia` and as binary yields different `argv`...
        parse(Float64, argv[1])
    catch
        parse(Float64, argv[2])
    end
    sol = TrimSimpleNonlinearSolve.minimize(λ)
    println(Core.stdout, sum(sol))
    return 0
end

This code runs just fine from the repl, and also works when we move the entire cache statement to const. However, like this it fails during trimming.

How to reproduce

git clone [email protected]:RomeoV/TrimSimpleNonlinearSolve.jl.git
cd TrimSimpleNonlinearSolve.jl
git checkout 160299f064c630402fc64d6fd96c4e9ab177a11e
juliaup override set 1.12
make

Other things I have tried

Since it seems just the methoderror is missing, I have tried to explicitly run stuff like Base.Enums.namemap(ReturnCode.T) on the trimming path. However it doesn't seem to help. I am also wondering if perhaps the enum is evaluated in the wrong world age and therefore the method is not available anymore... however, I don't know how to debug this.

Closing this should enable closing #59215 and maybe SciML/NonlinearSolve.jl#665.

Metadata

Metadata

Assignees

No one assigned

    Labels

    juliactrimmingIssues with trimming functionality or PR's relevant to its performance/functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions