JuliaDebug / JuliaInterpreter.jl

Interpreter for Julia code
Other
162 stars 34 forks source link

@interpret fails for Zygote and `eltype` #476

Closed torfjelde closed 3 years ago

torfjelde commented 3 years ago

Came across the following issue:

julia> using Zygote, JuliaInterpreter
[ Info: Precompiling Zygote [e88e6eb3-aa80-5325-afca-941959d7151f]

julia> f(x) = (eltype(x); sum(x))
f (generic function with 1 method)

julia> g(x) = Zygote.gradient(f, x)
g (generic function with 1 method)

julia> 

julia> JuliaInterpreter.@interpret g([1.0]) # × fails
ERROR: unrecognized isdefined node $(QuoteNode(Float64))
Stacktrace:
  [1] error(::String, ::QuoteNode)
    @ Base ./error.jl:42
  [2] check_isdefined(frame::Frame, node::Any)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:425
  [3] eval_rhs(recurse::Any, frame::Frame, node::Expr)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:391
  [4] step_expr!(recurse::Any, frame::Frame, node::Any, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:538
  [5] step_expr!(recurse::Any, frame::Frame, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:588
  [6] finish!(recurse::Any, frame::Frame, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/commands.jl:14
  [7] finish_and_return!
    @ ~/.julia/packages/JuliaInterpreter/moWwC/src/commands.jl:30 [inlined]
  [8] evaluate_call_recurse!(recurse::Any, frame::Frame, call_expr::Expr; enter_generated::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:240
  [9] evaluate_call_recurse!
    @ ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:201 [inlined]
 [10] eval_rhs(recurse::Any, frame::Frame, node::Expr)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:395
--- the last 7 lines are repeated 5 more times ---
 [46] step_expr!(recurse::Any, frame::Frame, node::Any, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:538
 [47] step_expr!(recurse::Any, frame::Frame, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/interpret.jl:588
 [48] finish!(recurse::Any, frame::Frame, istoplevel::Bool)
    @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/moWwC/src/commands.jl:14
 [49] finish_and_return!
    @ ~/.julia/packages/JuliaInterpreter/moWwC/src/commands.jl:30 [inlined]
 [50] finish_and_return! (repeats 2 times)
    @ ~/.julia/packages/JuliaInterpreter/moWwC/src/commands.jl:34 [inlined]

Not clear to me if this is Zygote doing something weird or if this is JuliaInterpreter lacking a support for this particular case. Anyways, hope this is useful!

Packages
@v1.6) pkg> st --manifest
      Status `~/.julia/environments/v1.6/Manifest.toml`
  [621f4979] AbstractFFTs v1.0.1
  [6e4b80f9] BenchmarkTools v0.6.0
  [082447d4] ChainRules v0.7.60
  [d360d2e6] ChainRulesCore v0.9.38
  [da1fd8a2] CodeTracking v1.0.5
  [bbf7d656] CommonSubexpressions v0.3.0
  [34da2185] Compat v3.27.0
  [8f4d0f93] Conda v1.5.1
  [a8cc5b0e] Crayons v4.0.4
  [163ba53b] DiffResults v1.0.3
  [b552c78f] DiffRules v1.0.2
  [1a297f60] FillArrays v0.11.7
  [f6369f11] ForwardDiff v0.10.18
  [cd3eb016] HTTP v0.9.5
  [7073ff75] IJulia v1.23.2
  [7869d1d1] IRTools v0.4.2
  [83e8ac13] IniFile v0.5.0
  [692b3bcd] JLLWrappers v1.2.0
  [682c06a0] JSON v0.21.1
  [aa1ae85d] JuliaInterpreter v0.8.13
  [16fef848] LiveServer v0.6.4
  [6f1432cf] LoweredCodeUtils v1.2.9
  [1914dd2f] MacroTools v0.5.6
  [739be429] MbedTLS v1.0.3
  [77ba4419] NaNMath v0.3.5
  [bac558e1] OrderedCollections v1.4.0
  [69de0a69] Parsers v1.1.0
  [189a3867] Reexport v1.0.0
  [ae029012] Requires v1.1.3
  [295af30f] Revise v3.1.14
  [b85f4697] SoftGlobalScope v1.1.0
  [276daf66] SpecialFunctions v1.3.0
  [90137ffa] StaticArrays v1.1.1
  [5c2747f8] URIs v1.2.0
  [81def892] VersionParsing v1.2.0
  [c2297ded] ZMQ v1.2.1
  [e88e6eb3] Zygote v0.6.9
  [700de1a5] ZygoteRules v0.2.1
  [efe28fd5] OpenSpecFun_jll v0.5.3+4
  [8f1865be] ZeroMQ_jll v4.3.2+6
  [a9144af2] libsodium_jll v1.0.18+1
  [0dad84c5] ArgTools
  [56f22d72] Artifacts
  [2a0f44e3] Base64
  [ade2ca70] Dates
  [8bb1440f] DelimitedFiles
  [8ba89e20] Distributed
  [f43a241f] Downloads
  [7b1f6079] FileWatching
  [b77e0a4c] InteractiveUtils
  [b27032c2] LibCURL
  [76f85450] LibGit2
  [8f399da3] Libdl
  [37e2e46d] LinearAlgebra
  [56ddb016] Logging
  [d6f4376e] Markdown
  [a63ad114] Mmap
  [ca575930] NetworkOptions
  [44cfe95a] Pkg
  [de0858da] Printf
  [3fa0cd96] REPL
  [9a3f8284] Random
  [ea8e919c] SHA
  [9e88b42a] Serialization
  [1a1011a3] SharedArrays
  [6462fe0b] Sockets
  [2f01184e] SparseArrays
  [10745b16] Statistics
  [fa267f1f] TOML
  [a4e569a6] Tar
  [8dfed614] Test
  [cf7118a7] UUIDs
  [4ec0a83e] Unicode
  [e66e0078] CompilerSupportLibraries_jll
  [deac9b47] LibCURL_jll
  [29816b5a] LibSSH2_jll
  [c8ffd9c3] MbedTLS_jll
  [14a3606d] MozillaCACerts_jll
  [83775a58] Zlib_jll
  [8e850ede] nghttp2_jll
  [3f19e933] p7zip_jll
pfitzseb commented 3 years ago

So the MWE here is something like

julia> @generated f() = Expr(:isdefined, :($(QuoteNode(Float64))))
f (generic function with 1 method)

julia> f()
true

julia> JuliaInterpreter.@interpret f()
ERROR: unrecognized isdefined node $(QuoteNode(Float64))

which seems like a weird function to write anyways (in Zygote it's generated somewhere here).

diff --git a/src/interpret.jl b/src/interpret.jl
index ba26275..089e4a7 100644
--- a/src/interpret.jl
+++ b/src/interpret.jl
@@ -421,6 +421,8 @@ function check_isdefined(frame, @nospecialize(node))
         return isdefined(node.mod, node.name)
     elseif isa(node, Symbol)
         return isdefined(moduleof(frame), node)
+    elseif isa(node, QuoteNode)
+        return isdefined(moduleof(frame), Symbol(node.value))
     end
     error("unrecognized isdefined node ", node)
 end

is a possible fix, but I don't know if it actually makes sense...

simeonschaub commented 3 years ago

I think the right return value here would just be true, see #477. A lot of Cassette style code transformations replace slots with QuoteNodes, so I think we should support this.

torfjelde commented 3 years ago

Oh wow, that was quick! Thanks!