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

Workaround UndefVarError: A not defined #156

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

YingboMa
Copy link
Member

This PR fixes the following error, though, maybe something more sinister is going on. Unfortunately, I cannot find an MWE. I understand that this PR is not perfect. However, for the time being, I wonder if this PR can be merged and tagged since it is blocking the release of ForwardDiff2.

ERROR: UndefVarError: A not defined
Stacktrace:
 [1] macro expansion at ./show.jl:562 [inlined]
 [2] call(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(Core.apply_type), ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},V,P} where P}, ::Type{Array{Operation,1}}) at /Users/yingboma/.julia/dev/Cassette/src/context.jl:454
 [3] fallback(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::Function, ::Vararg{Any,N} where N) at /Users/yingboma/.julia/dev/Cassette/src/context.jl:445
 [4] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(Core.apply_type), ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},V,P} where P}, ::Type{Array{Operation,1}}) at /Users/yingboma/.julia/packages/Cassette/kbN4l/src/overdub.jl:486
 [5] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(typejoin), ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},ModelingToolkit.Constant,Array{Operation,1}}}, ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Operation,1}}}) at ./promotion.jl:105
 [6] _promote_typejoin at ./promotion.jl:131 [inlined]
 [7] promote_typejoin at ./promotion.jl:130 [inlined]
 [8] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(Base.promote_typejoin), ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},ModelingToolkit.Constant,Array{Operation,1}}}, ::Type{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Operation,1}}}) at /Users/yingboma/.julia/packages/Cassette/kbN4l/src/overdub.jl:0
 [9] copyto_nonleaf! at ./broadcast.jl:1009 [inlined]
 [10] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(Base.Broadcast.copyto_nonleaf!), ::Array{ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},ModelingToolkit.Constant,Array{Operation,1}},2}, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2},Tuple{Base.OneTo{Int64},Base.OneTo{Int64}},typeof(ForwardDiff2._seed),Tuple{Base.RefValue{ForwardDiff2.DualArray{ForwardDiff2.Tag{Nothing},ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Expression,1}},1,Array{Operation,1},Array{Expression,2}}},Base.Broadcast.Extruded{CartesianIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}},Tuple{Bool,Bool},Tuple{Int64,Int64}}}}, ::CartesianIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}, ::CartesianIndex{2}, ::Int64) at /Users/yingboma/.julia/packages/Cassette/kbN4l/src/overdub.jl:0
 [11] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::typeof(ForwardDiff2.seed), ::ForwardDiff2.DualArray{ForwardDiff2.Tag{Nothing},ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Expression,1}},1,Array{Operation,1},Array{Expression,2}}) at ./broadcast.jl:857
 [12] deriv at /Users/yingboma/.julia/dev/ForwardDiff2/src/api.jl:36 [inlined]
 [13] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::ForwardDiff2.var"#deriv#31"{typeof(prod)}, ::ForwardDiff2.DualArray{ForwardDiff2.Tag{Nothing},ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Expression,1}},1,Array{Operation,1},Array{Expression,2}}) at /Users/yingboma/.julia/packages/Cassette/kbN4l/src/overdub.jl:0
 [14] #28 at /Users/yingboma/.julia/dev/ForwardDiff2/src/api.jl:38 [inlined]
 [15] overdub(::Cassette.Context{nametype(DualContext),Nothing,Nothing,ForwardDiff2.var"##PassType#402",Nothing,Cassette.DisableHooks}, ::ForwardDiff2.var"#28#33"{ForwardDiff2.DualArray{ForwardDiff2.Tag{Nothing},ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},Operation,Array{Expression,1}},1,Array{Operation,1},Array{Expression,2}},ForwardDiff2.var"#deriv#31"{typeof(prod)}}) at /Users/yingboma/.julia/packages/Cassette/kbN4l/src/overdub.jl:0
 [16] dualrun(::Function) at /Users/yingboma/.julia/dev/ForwardDiff2/src/dual_context.jl:148
 [17] (::ForwardDiff2.var"#deriv#31"{ForwardDiff2.var"#deriv#31"{typeof(prod)}})(::Array{Operation,1}) at /Users/yingboma/.julia/dev/ForwardDiff2/src/api.jl:38
 [18] top-level scope at REPL[21]:1

@YingboMa
Copy link
Member Author

The above error happens when I do

using ForwardDiff2: D; using ModelingToolkit
@variables a[1:3]
D(D(prod))(a)'

@vchuravy
Copy link
Member

vchuravy commented Jan 11, 2020

I would like to understand this a bit better first, which of the two types are undefined? This needs an upstream bug-report as well.

The failing tests are #155

@YingboMa
Copy link
Member Author

With

diff --git a/src/context.jl b/src/context.jl
index d02a16d..d98b74f 100644
--- a/src/context.jl
+++ b/src/context.jl
@@ -451,7 +451,9 @@ See also:  [`canrecurse`](@ref), [`overdub`](@ref), [`recurse`](@ref), [`prehook
 # to `Core.apply_type`. In the future, it would be best for Julia's compiler to better handle
 # varargs calls to such functions with type arguments, or at least provide a better way to
 # force specialization on the type arguments.
-@inline call(::ContextUntagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)
+@inline function call(::ContextUntagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B}
+    @isdefined(A) && @isdefined(B) ? f(A, B) : (Main.__a[] = a; f(@show(a), b))
+end
 @inline call(::ContextTagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)

 """

I got

julia> using ForwardDiff2: D; using ModelingToolkit

julia> @variables v[1:3];

julia> __a = Ref{Any}();

julia> D(D(prod))(v)';
a = ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},V,P} where P

julia> dump(__a[])
UnionAll
  var: TypeVar
    name: Symbol P
    lb: Core.TypeofBottom Union{}
    ub: Any
  body: ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},V,P} <: Real
    value::V
    partials::P

That is super weird...

@vchuravy
Copy link
Member

a = ForwardDiff2.Dual{ForwardDiff2.Tag{Nothing},V,P} where P it is as if there is a where V missing.

Comment on lines +454 to +455
@inline call(::ContextUntagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)
@inline call(::ContextTagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@inline call(::ContextUntagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)
@inline call(::ContextTagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = @isdefined(A) && @isdefined(B) ? f(A, B) : f(a, b)
@inline call(::ContextUntagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = f(a, b)
@inline call(::ContextTagged, f::typeof(Core.apply_type), a::Type{A}, b::Type{B}) where {A,B} = f(a, b)

where {A} preserves only the equality of a type and not its identity. Thus, especially in a context like this, you must always use the value, to avoid corrupting the meaning of the expression. For example, the former may equate Dict{K,V} where {K,V} with Dict{K,V} where {V,K} since they are equivalent types, but the call to apply_type should yield very different results for those two based upon their distinct identity.

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

Successfully merging this pull request may close these issues.

None yet

3 participants