From Flux.jl’s source code here:
mutable struct Recur{T}
cell::T
init
state
end
Recur(m, h = hidden(m)) = Recur(m, h, h)
function (m::Recur)(xs...)
h, y = m.cell(m.state, xs...)
m.state = h
return y
end
it looks like Recur struct, which is used for every recurrent layer, does mutation of its state field in the forward pass. But Zygote.jl does not support mutation, so why is this not throwing something like ERROR: Mutation is not supported! as it usually does in such cases?
For a context of where this came up: I was implementing my custom stateful layer. Initially, I just defined MyCustomRecurrentCell similarly to RNNCell and relied on Recur to handle the MyCustomRecurrentCell’s state mutation, just like RNNCell does. But then I discovered that because Recur’s fields are not type annotated I was getting Any type outputs for my state which was propagating to all the other layer and I was getting Any everywhere because of this. Then I filed this issue and decided to reimplement Recur with type annotated fields. When I did so, I’m now getting something like Mutation is not supported error. So I was wondering how is Recur able to get away with mutating state?