I’m messing around with ForwardDiff, trying to write some type stable code, and have found an instance where typeof
does not properly infer the type. I’m a bit stuck as to what to try here!
I think this particular function used to infer properly, before I switched to Julia 1.9, but many other things have changed as well…
The function in question:
function hessian(f, x::SVector)
# T = typeof(HessiansTag(x))
T = typeof(Tag(f, eltype(x)))
d1 = dualize(T, x)
d2 = dualize(T, d1)
yd2 = f(d2)
yd1 = value(T, yd2)
val = value(T, yd1)
dgrad = extract_jacobian(T, yd2, x)
grad = value(T, dgrad)
hess = extract_jacobian(T, dgrad, x)
result = DiffResults.ImmutableDiffResult(val, (grad, hess))
return result
end
The output of @code_warntype is below.
Note that %2 is infered, but typeof(%2) is not
MethodInstance for ForwardDiff.hessian(::RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, ::StaticArraysCore.SVector{9, Float64})
from hessian(f, x::StaticArraysCore.SVector) @ RobotDynamics.Hessians C:\Users\dan_l\Dropbox (Cambridge University)\shared_Daniel\code\RobotDynamics.jl\src\hessians.jl:47
Arguments
#self#::Core.Const(ForwardDiff.hessian)
f::RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}
x::StaticArraysCore.SVector{9, Float64}
Locals
result::DiffResults.ImmutableDiffResult{2}
hess::Any
grad::Any
dgrad::Any
val::Any
yd1::Any
yd2::Any
d2::Any
d1::Any
T::Type{ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}}
Body::DiffResults.ImmutableDiffResult{2}
1 ─ %1 = RobotDynamics.Hessians.eltype(x)::Core.Const(Float64)
│ %2 = RobotDynamics.Hessians.Tag(f, %1)::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}())
│ (T = RobotDynamics.Hessians.typeof(%2))
│ (d1 = RobotDynamics.Hessians.dualize(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), x))
│ (d2 = RobotDynamics.Hessians.dualize(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), d1))
│ (yd2 = (f)(d2))
│ (yd1 = RobotDynamics.Hessians.value(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), yd2))
│ (val = RobotDynamics.Hessians.value(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), yd1))
│ (dgrad = RobotDynamics.Hessians.extract_jacobian(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), yd2, x))
│ (grad = RobotDynamics.Hessians.value(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), dgrad))
│ (hess = RobotDynamics.Hessians.extract_jacobian(T::Core.Const(ForwardDiff.Tag{RobotDynamics.var"#f_kinematics#8"{RobotDynamics.RBTree{22, Union{RobotDynamics.Prismatic{Float64, Int64}, RobotDynamics.Revolute{Float64, Int64}, RobotDynamics.Rigid{Float64}, RobotDynamics.Rail{Float64, Int64}}}}, Float64}), dgrad, x))
│ %12 = DiffResults.ImmutableDiffResult::Core.Const(DiffResults.ImmutableDiffResult)
│ %13 = val::Any
│ %14 = Core.tuple(grad, hess)::Tuple{Any, Any}
│ (result = (%12)(%13, %14))
└── return result