diff --git a/src/tangent_types/abstract_zero.jl b/src/tangent_types/abstract_zero.jl index afa5b130f..f5f213672 100644 --- a/src/tangent_types/abstract_zero.jl +++ b/src/tangent_types/abstract_zero.jl @@ -109,7 +109,11 @@ zero_tangent(x::Number) = zero(x) @generated function zero_tangent(primal) has_mutable_tangent(primal) || return ZeroTangent() # note this takes care of tuples zfield_exprs = map(fieldnames(primal)) do fname - fval = Expr(:call, zero_tangent, Expr(:call, getfield, :primal, QuoteNode(fname))) + fval = if isdefined(primal, fname) + Expr(:call, zero_tangent, Expr(:call, getfield, :primal, QuoteNode(fname))) + else + ZeroTangent() + end Expr(:kw, fname, fval) end backing_expr = Expr(:tuple, Expr(:parameters, zfield_exprs...)) diff --git a/test/tangent_types/abstract_zero.jl b/test/tangent_types/abstract_zero.jl index c9442707d..501bc876a 100644 --- a/test/tangent_types/abstract_zero.jl +++ b/test/tangent_types/abstract_zero.jl @@ -174,7 +174,7 @@ end @test zero_tangent([1.0, 2.0]) == [0.0, 0.0] @test zero_tangent([[1.0, 2.0], [3.0]]) == [[0.0, 0.0], [0.0]] - @testset "undef elements" begin + @testset "undef elements Vector" begin x = Vector{Vector{Float64}}(undef, 3) x[2] = [1.0, 2.0] dx = zero_tangent(x) @@ -196,4 +196,20 @@ end @test length(db) == 3 @test db isa Vector end + + @testset "undef fields struct" begin + dx = zero_tangent(Core.Box()) + @test dx.contents isa ZeroTangent + @test (dx.contents = 2.0) == 2.0 # should be assignable + + mutable struct MyPartiallyDefinedStruct + intro::Float64 + contents::Number + MyPartiallyDefinedStruct(x) = new(x) + end + dy = zero_tangent(MyPartiallyDefinedStruct(1.5)) + @test iszero(dy.intro) + @test iszero(dy.contents) + @test (dy.contents = 2.0) == 2.0 # should be assignable + end end