Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

custom getproperty of mutable struct fails #685

Closed
marius311 opened this issue Jun 14, 2020 · 2 comments
Closed

custom getproperty of mutable struct fails #685

marius311 opened this issue Jun 14, 2020 · 2 comments

Comments

@marius311
Copy link
Contributor

Here's a MWE on 0.4.20, basically I'm adding a custom property foo.x:

mutable struct Foo end
Base.getproperty(foo::Foo, k::Symbol) = k == :x ? 5 : getfield(foo,k)
Base.propertynames(::Foo) = (:x,)

foo = Foo()
gradient(y -> foo.x * y, 1)

which fails with:

ERROR: type Tuple has no field x
Stacktrace:
 [1] (::Zygote.var"#back#1962"{:x,Zygote.Context,Foo,Int64})(::Int64) at /home/marius/.julia/packages/Zygote/YeCEW/src/lib/lib.jl:212
 [2] #130#back at /home/marius/.julia/packages/ZygoteRules/6nssF/src/adjoint.jl:49 [inlined]
 [3] #15 at ./none:1 [inlined]
 [4] (::typeof((#15)))(::Int64) at /home/marius/.julia/packages/Zygote/YeCEW/src/compiler/interface2.jl:0
 [5] (::Zygote.var"#36#37"{typeof((#15))})(::Int64) at /home/marius/.julia/packages/Zygote/YeCEW/src/compiler/interface.jl:46
 [6] gradient(::Function, ::Int64) at /home/marius/.julia/packages/Zygote/YeCEW/src/compiler/interface.jl:55
 [7] top-level scope at none:0

Note if I make the struct immutable its fine. Another solution appears to be defining the following, but I really don't know what I'm doing here so maybe this is not correct in general:

Zygote.grad_mut(foo::Foo) = Ref{Any}((;(propertynames(foo) .=> nothing)...))
@ablaom
Copy link

ablaom commented Sep 11, 2020

Also running into this issue. Prevents use of Zygote with matrices wrapped as tables using Tables.matrix, for example.

In my case the struct is immutable and the error is still there (Zygote = v0.5.6):

struct Foo
    z::Float64
end

Base.propertynames(Foo) = (:z_squared,)
Base.getproperty(f::Foo, s::Symbol) =
    s in propertynames(Foo) ? getfield(f, :z)^2 : throw(ArgumentError)

foo = Foo(2.0)
julia> foo.z_squared
4.0

loss(x) = x*getfield(foo, :z)
julia> loss(3)
6.0

julia> gradient(loss, 1.0)
ERROR: ArgumentError
Stacktrace:
 [1] getproperty(::Foo, ::Symbol) at ./REPL[11]:1
 [2] adjoint at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/lib/lib.jl:197 [inlined]
 [3] _pullback(::Zygote.Context, ::typeof(ZygoteRules.literal_getproperty), ::Foo, ::Val{:z at /Users/anthony/.julia/packages/ZygoteRules/6nssF/src/adjoint.jl:47
 [4] _pullback(::Zygote.Context, ::typeof(getfield), ::Foo, ::Symbol) at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/lib/lib.jl:214
 [5] loss at ./REPL[20]:1 [inlined]
 [6] _pullback(::Zygote.Context, ::typeof(loss), ::Float64) at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/compiler/interface2.jl:0
 [7] _pullback(::Function, ::Float64) at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/compiler/interface.jl:38
 [8] pullback(::Function, ::Float64) at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/compiler/interface.jl:44
 [9] gradient(::Function, ::Float64) at /Users/anthony/.julia/packages/Zygote/Xgcgs/src/compiler/interface.jl:53
 [10] top-level scope at REPL[23]:1
 [11] eval(::Module, ::Any) at ./boot.jl:331
 [12] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [13] run_backend(::REPL.REPLBackend) at /Users/anthony/.julia/packages/Revise/BqeJF/src/Revise.jl:1184

julia> versioninfo()
Julia Version 1.4.2

@marius311
Copy link
Contributor Author

Both MWEs from this issue appear fixed with at least Zygote v0.6.11 (maybe before, I havent bisected), so closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants