Using ForwardDiff for Symbolic.derivative() definition

I’ve only been playing with MTK.jl for a day or two, but I’m really impressed - the workflow here is so much nicer than using a dedicated acausal modelling language! I’m running into situations where judicious function registration is advisable, and I’d like to understand how flexibly derivatives can be specified. ModelingToolkit.jl enables you to register functions via @register_symbolic, and also to attach derivative information to those functions. This may be handy when the function is too big and scary to be converted entirely into symbolic form. For example, we can do the following:

function foo_f(t)
    return t^2
end
@variables t
@register_symbolic foo_f(t)
Symbolics.derivative(::typeof(foo_f), args::NTuple{1,Any}, ::Val{1}) = 2*args[1]
dfdt = Symbolics.derivative(foo_f, t). #2t
substitute(dfdt, t => 2) #4

I’ve been playing around with automatically calculating derivatives via ForwardDiff.jl, but I’m running into some issues. Directly defining a new method for Symbolics.derivative works fine:

function foo_f2(x)
    return x^2
end
@variables t
@register_symbolic foo_f2(t)
Symbolics.derivative(::typeof(foo_f2), t::Num) = ForwardDiff.derivative(foo_f2, t)
dfdt = Symbolics.derivative(foo_f2, t) #2t
substitute(dfdt, t => 2) #4

But doing the proper thing as described in the docs gives an error:

function foo_f3(x)
    return x^2
end
@variables t
@register_symbolic foo_f3(t)
Symbolics.derivative(::typeof(foo_f3), args::NTuple{1,Any}, ::Val{1}) = ForwardDiff.derivative(foo_f3, args[1])
dfdt_3 = Symbolics.derivative(foo_f3, t)
substitute(dfdt_3, t => 2)
ERROR: MethodError: no method matching derivative(::typeof(foo_f3), ::SymbolicUtils.BasicSymbolic{Real})
The function `derivative` exists, but no method is defined for this combination of argument types.

I’m curious if it’s possible to get ForwardDiff and Symbolics.derivative to play nice with each other for a simple example like this. Also, will the second approach above (directly overriding the helper function Symbolic.derivative(::typeof(foo_f2), t::Num)) work, or is this asking for trouble later on?