Enzyme.jl
Enzyme.jl copied to clipboard
MethodError on dynamic `Val` construction
MWE:
using Enzyme
f(::Val{D}) where D = prod(D)
mwe(x, t) = x / f(Val(t))
Enzyme.autodiff(mwe, Active, Active(1.0), Const((1, 2)))
Results in:
ERROR: LoadError: MethodError: no method matching DataType()
Stacktrace:
[1] macro expansion
@ ~/.julia/packages/GPUCompiler/EV8pB/src/cache.jl:0 [inlined]
[2] specialization_id(job::GPUCompiler.CompilerJob{Enzyme.Compiler.EnzymeTarget, Enzyme.Compiler.EnzymeCompilerParams, GPUCompiler.FunctionSpec{DataType, Tuple{}}})
@ GPUCompiler ~/.julia/packages/GPUCompiler/EV8pB/src/cache.jl:12
[3] thunk
@ ~/.julia/dev/Enzyme/src/compiler.jl:4462 [inlined]
[4] thunk(f::Type{Val{(1, 2)}}, df::Nothing, ::Type{Const{Val{(1, 2)}}}, tt::Type{Tuple{}}, ::Val{Enzyme.API.DEM_ReverseModePrimal}, ::Val{0x0000000000000001})
@ Enzyme.Compiler ~/.julia/dev/Enzyme/src/compiler.jl:4456
in expression starting at /home/brianc/projects/juliamwes/enzyme/mwe.jl:6
The above was reduced from https://github.com/FluxML/NNlib.jl/blob/master/src/impl/conv_direct.jl#L47-L56, where we use this pattern + a function barrier for type stability.
On main I get a slightly better answer:
julia> Enzyme.autodiff(mwe, Active, Active(1.0), Const((1, 2)))
ERROR: MethodError: no method matching typeof(mwe)(::Float64, ::Tuple{Int64, Int64})
Stacktrace:
[1] macro expansion
@ ~/.julia/packages/GPUCompiler/1FdJy/src/cache.jl:0 [inlined]
[2] specialization_id(job::GPUCompiler.CompilerJob{Enzyme.Compiler.EnzymeTarget, Enzyme.Compiler.EnzymeCompilerParams, GPUCompiler.FunctionSpec{DataType, Tuple{Float64, Tuple{Int64, Int64}}}})
@ GPUCompiler ~/.julia/packages/GPUCompiler/1FdJy/src/cache.jl:12
[3] thunk(f::typeof(mwe), df::Nothing, ::Type{Duplicated{Any}}, tt::Type{Tuple{Active{Float64}, Const{Tuple{Int64, Int64}}}}, ::Val{Enzyme.API.DEM_ReverseModeGradient}, ::Val{1}, ::Val{false})
@ Enzyme.Compiler ~/src/Enzyme/src/compiler.jl:4461
[4] autodiff(::typeof(mwe), ::Type{Active}, ::Active{Float64}, ::Vararg{Any})
@ Enzyme ~/src/Enzyme/src/Enzyme.jl:263
[5] top-level scope
@ REPL[4]:1
So a Active return doesn't like Any
julia> using Enzyme
julia> f(x) = Base.inferencebarrier(x)
f (generic function with 1 method)
julia> Enzyme.autodiff(f, Active, Active(1.0))
ERROR: MethodError: no method matching setindex!(::Tuple{Ptr{Nothing}, Float64, Float64}, ::Float64, ::Int64)
Stacktrace:
[1] autodiff(f::typeof(f), #unused#::Type{Active}, args::Active{Float64})
@ Enzyme ~/src/Enzyme/src/Enzyme.jl:269
[2] top-level scope
@ REPL[3]:1
julia> @code_typed mwe(1.0, (1, 2))
CodeInfo(
1 ─ %1 = invoke Main.Val(t::Tuple{Int64, Int64})::Val
│ %2 = Main.f(%1)::Any
│ %3 = (x / %2)::Any
└── return %3
) => Any
But even with:
julia> f(::Val{D}) where D = prod(D)
julia> @code_typed mwe(1.0, (1, 2))
CodeInfo(
1 ─ %1 = Main.Float64::Type{Float64}
│ %2 = invoke Main.Val(t::Tuple{Int64, Int64})::Val
│ %3 = Main.f(%2)::Any
│ %4 = (x / %3)::Any
│ %5 = Base.convert(%1, %4)::Any
│ Core.typeassert(%5, %1)::Float64
│ %7 = π (%5, Float64)
└── return %7
) => Float64
julia> using Enzyme
julia> Enzyme.autodiff(mwe, Active, Active(1.0), Const((1, 2)))
ERROR: MethodError: no method matching DataType()
Stacktrace:
[1] macro expansion
@ ~/src/GPUCompiler/src/cache.jl:0 [inlined]
[2] specialization_id(job::GPUCompiler.CompilerJob{Enzyme.Compiler.EnzymeTarget, Enzyme.Compiler.EnzymeCompilerParams, GPUCompiler.FunctionSpec{DataType, Tuple{}}})
@ GPUCompiler ~/src/GPUCompiler/src/cache.jl:12
[3] thunk(f::Type{Val{(1, 2)}}, df::Nothing, ::Type{Const{Val{(1, 2)}}}, tt::Type{Tuple{}}, ::Val{Enzyme.API.DEM_ReverseModePrimal}, ::Val{0x0000000000000001}, ::Val{true})
@ Enzyme.Compiler ~/src/Enzyme/src/compiler.jl:4461
[4] thunk(f::Type{Val{(1, 2)}}, df::Nothing, ::Type{Const{Val{(1, 2)}}}, tt::Type{Tuple{}}, ::Val{Enzyme.API.DEM_ReverseModePrimal}, ::Val{0x0000000000000001})
@ Enzyme.Compiler ~/src/Enzyme/src/compiler.jl:4456
We fail on the call to the constructor.
Present error:
julia> Enzyme.autodiff(mwe, Active, Active(1.0), Const((1, 2)))
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] unsafe_convert
@ /mnt/Data/git/Enzyme.jl/src/compiler.jl:4357 [inlined]
[2] macro expansion
@ /mnt/Data/git/Enzyme.jl/src/compiler.jl:4600 [inlined]
[3] enzyme_call
@ /mnt/Data/git/Enzyme.jl/src/compiler.jl:4396 [inlined]
[4] AugmentedForwardThunk
@ /mnt/Data/git/Enzyme.jl/src/compiler.jl:4387 [inlined]
[5] autodiff
@ /mnt/Data/git/Enzyme.jl/src/Enzyme.jl:272 [inlined]
[6] autodiff(::typeof(mwe), ::Type{Active}, ::Active{Float64}, ::Const{Tuple{Int64, Int64}})
@ Enzyme /mnt/Data/git/Enzyme.jl/src/Enzyme.jl:411
[7] top-level scope
@ REPL[4]:1
Duplicate of https://github.com/EnzymeAD/Enzyme.jl/issues/293
on #408
julia> using Enzyme
julia> f(::Val{D}) where D = prod(D)
f (generic function with 1 method)
julia> mwe(x, t) = x / f(Val(t))
mwe (generic function with 1 method)
julia> Enzyme.autodiff(mwe, Active, Active(1.0), Const((1, 2)))
ERROR: MethodError: guess_activity(::Type{Union{}}) is ambiguous. Candidates:
guess_activity(::Type{T}) where T<:AbstractFloat in Enzyme at /home/vchuravy/src/Enzyme/src/Enzyme.jl:142
guess_activity(::Type{T}) where T<:(Complex{<:AbstractFloat}) in Enzyme at /home/vchuravy/src/Enzyme/src/Enzyme.jl:149
guess_activity(::Type{T}) where T<:AbstractArray in Enzyme at /home/vchuravy/src/Enzyme/src/Enzyme.jl:157
Possible fix, define
guess_activity(::Type{Union{}})