Skip to content

Puzzling failure to set the value of a symbol #380

@timholy

Description

@timholy

Looking into timholy/Revise.jl#429, I applied the following patch to JuliaInterpreter (the key part is the first block of changes to do_assignment!, the rest is just me being paranoid):

diff --git a/src/interpret.jl b/src/interpret.jl
index 1700ae6..4e446d2 100644
--- a/src/interpret.jl
+++ b/src/interpret.jl
@@ -349,7 +349,13 @@ function do_assignment!(frame, @nospecialize(lhs), @nospecialize(rhs))
     elseif isa(lhs, GlobalRef)
         Core.eval(lhs.mod, :($(lhs.name) = $(QuoteNode(rhs))))
     elseif isa(lhs, Symbol)
-        Core.eval(moduleof(code), :($lhs = $(QuoteNode(rhs))))
+        @show lhs rhs typeof(rhs) moduleof(code)
+        dump(lhs)
+        dump(rhs)
+        newex = :($lhs = $(QuoteNode(rhs)))
+        @show newex
+        ret = Core.eval(moduleof(code), :($lhs = $(QuoteNode(rhs))))
+        @show ret isdefined(moduleof(code), lhs)
     end
 end
 
@@ -435,7 +441,7 @@ function step_expr!(@nospecialize(recurse), frame, @nospecialize(node), istoplev
     # For profiling:
     # location_key = (scopeof(frame), pc)
     # _location[location_key] = get(_location, location_key, 0) + 1
-    try
+    # try
         if isa(node, Expr)
             if node.head == :(=)
                 lhs, rhs = node.args
@@ -532,13 +538,14 @@ function step_expr!(@nospecialize(recurse), frame, @nospecialize(node), istoplev
             # FIXME: undefine the slot?
         elseif istoplevel && isa(node, LineNumberNode)
         elseif istoplevel && isa(node, Symbol)
+            @show moduleof(frame) node
             rhs = getfield(moduleof(frame), node)
         else
             rhs = @lookup(frame, node)
         end
-    catch err
-        return handle_err(recurse, frame, err)
-    end
+    # catch err
+    #     return handle_err(recurse, frame, err)
+    # end
     @isdefined(rhs) && isa(rhs, BreakpointRef) && return rhs
     if isassign(frame, pc)
         if !@isdefined(rhs)

Then I run the example (I named the module Manu) and get this:

julia> 1+1   # trigger a revision
moduleof(frame) = Manu
node = Symbol("#coinflip#11#16")
moduleof(frame) = Manu
node = Symbol("##inner_function#446#17")
moduleof(frame) = Manu
node = Symbol("##inner_function#446#17")
moduleof(frame) = Manu
node = Symbol("##inner_function#446#17")
moduleof(frame) = Manu
node = Symbol("#coinflip#15")
lhs = Symbol("#s114")
rhs = #s114
typeof(rhs) = TypeVar
moduleof(code) = Manu
Symbol #s114
TypeVar
  name: Symbol #s114
  lb: Core.TypeofBottom Union{}
  ub: Any
newex = :(var"#s114" = $(QuoteNode(#s114)))
ret = #s114
isdefined(moduleof(code), lhs) = false          # HERE'S THE BIZARRE BIT. WHY IS THIS FALSE?
moduleof(frame) = Manu
node = Symbol("#s114")
┌ Error: evaluation error starting at /home/tim/.julia/dev/Revise/test/Manu.jl:8
│   mod = Manu
│   ex =quote#= /home/tim/.julia/dev/Revise/test/Manu.jl:8 =#function test_fun()
│            #= /home/tim/.julia/dev/Revise/test/Manu.jl:10 =#
│            p_true = 0.5#= /home/tim/.julia/dev/Revise/test/Manu.jl:13 =#
│            Ns = 0:100#= /home/tim/.julia/dev/Revise/test/Manu.jl:16 =#
│            Random.seed!(12)
│            #= /home/tim/.julia/dev/Revise/test/Manu.jl:17 =#
│            data = rand(Bernoulli(p_true), last(Ns))
│            #= /home/tim/.julia/dev/Revise/test/Manu.jl:21 =##= /home/tim/.julia/dev/Revise/test/Manu.jl:21 =# @model (coinflip(y, ::Type{T}=Float64) where T) = begin#= /home/tim/.julia/dev/Revise/test/Manu.jl:21 =##= /home/tim/.julia/dev/Revise/test/Manu.jl:23 =#
│                        p ~ Beta(1, 1)
│                        #= /home/tim/.julia/dev/Revise/test/Manu.jl:26 =#
│                        N = length(y)
│                        #= /home/tim/.julia/dev/Revise/test/Manu.jl:27 =#for n = 1:N
│                            #= /home/tim/.julia/dev/Revise/test/Manu.jl:29 =#
│                            y[n] ~ Bernoulli(p)
│                        endend#= /home/tim/.julia/dev/Revise/test/Manu.jl:34 =#
│            iterations = 1000#= /home/tim/.julia/dev/Revise/test/Manu.jl:35 =#
│            ϵ = 0.05#= /home/tim/.julia/dev/Revise/test/Manu.jl:36 =#
│            τ = 10#= /home/tim/.julia/dev/Revise/test/Manu.jl:39 =#
│            chain = sample(coinflip(data), HMC(ϵ, τ), iterations)
│            #= /home/tim/.julia/dev/Revise/test/Manu.jl:40 =#return chain
│        endend
│   exception =
│    UndefVarError: #s114 not defined
│    Stacktrace:
│     [1] step_expr!(::Any, ::JuliaInterpreter.Frame, ::Any, ::Bool) at /home/tim/.julia/dev/JuliaInterpreter/src/interpret.jl:542
└ @ Revise ~/.julia/packages/Revise/ZOWOa/src/lowered.jl:105
2

In case you missed it, the strange part is the isdefined(moduleof(code), lhs) = false; why, right after Core.evaling a symbol assignment, is that symbol not defined?

Just to make sure I'm not crazy, with the same patch applied:

julia> using JuliaInterpreter

julia> frame = JuliaInterpreter.prepare_thunk(Main, :(var"#s90" = TypeVar(Symbol("#s90"), Any)))
Frame for Main
  1 0  1%1 = Symbol("#s90")
  2 0%2 = TypeVar(%1, Any)
  3 0var"#s90" = %2


julia> JuliaInterpreter.finish!(frame, true)
lhs = Symbol("#s90")
rhs = #s90
typeof(rhs) = TypeVar
moduleof(code) = Main
Symbol #s90
TypeVar
  name: Symbol #s90
  lb: Core.TypeofBottom Union{}
  ub: Any
newex = :(var"#s90" = $(QuoteNode(#s90)))
ret = #s90
isdefined(moduleof(code), lhs) = true

I confess extreme bafflement. Any idea what's wrong? Note this warning:

[ Info: Precompiling Manu [top-level]
WARNING: Method definition (::getfield(Manu, Symbol("#coinflip#5")){#coinflip#1})() in module Manu at /home/tim/.julia/packages/Turing/xFzfF/src/core/compiler.jl:406 overwritten at /home/tim/.julia/packages/Turing/xFzfF/src/core/compiler.jl:412.
  ** incremental compilation may be fatally broken for this module **

I wonder if Turing.jl is breaking Julia?

Anyway, I'd really appreciate feedback, even if it's "That's weird. No clue."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions