Is this generated function for struct2tuple safe to use?

I’m not really sure if this function could be used safely when I have a struct with mutable fields in it:

@generated function struct2tuple(x::T) where T
    n = fieldcount(T)
    exprs = [:(getfield(x, $(i))) for i in 1:n]
    return Expr(:tuple, exprs...)
end

is it forbidden? It seems that the manual says something against this when talking about observing mutable states, but it seems to work fine e.g.

julia> struct A
           x::Vector{Int}
           y::Vector{Float64}
       end

julia> struct2tuple(A([1], [1.]))
([1], [1.0])

But I’m a total beginner in these kind of things so I’m unsure.

Maybe I’m wrong, but if “observing mutable states” means that I base any code generation decision on mutable values, then this should be safe.

Generated functions must not mutate or observe any non-constant global state (including, for example, IO, locks, non-local dictionaries, or using hasmethod).

you’re fine I think, you’re not mutating any non-constant global state, and I don’t think fieldcount(T) is a mutable global state.

technically fieldcount is a generic function which could be overloaded for a specific type.
But if that happens a lot of other things will probably break,
so you are already in hell.
This code is fine basically.

This doesn’t answer your question, but in your specific case you can replace the generated function by

struct2tuple(x::T) where T = ntuple(i -> getfield(x, i), Val(fieldcount(T)))

(I didn’t check that this remains efficient for structs with very many fields.)

Nice, yes, it seems to work fine in my use case. I had the same function without the Val and it wasn’t working efficiently, but with that it does.

Thanks a lot to all of you!

Also check ConstructionBase.jl: it has getfields(your_obj) and getproperties(your_obj).
It’s a very lightweight package, a large fraction of Julia ecosystem depends on it.