Let expression and garbage collection

Not sure if this is a bug, or if I misunderstand something about let. But
I think in the following snipped ret is unreachable, when gc() runs, yet it does not get collected.

function f end
let
    ret = []
    finalizer(ret, println)
    f() = ret
end

f()
f() = "something else"
f()
gc()

It’s not an issue with let:

julia> let ret = Ref(0)
         finalizer(ret, println)
         global f = ret
       end
Base.RefValue{Int64}(0)

julia> f
Base.RefValue{Int64}(0)

julia> f = 0
0

julia> gc()
Base.RefValue{Int64}(0)

I believe the issue is approximately that Julia doesn’t GC methods, merely updates the method table (ref 11695, but that’s only talking about object code specifically). You may have noticed that the finalizer does run when you cleanly exit Julia.

However, this doesn’t quite make sense in a few test cases I tried because the AST only appears to be storing a literal.

(by the way: finalizer should not cause a task switch, such as by performing I/O, but this was not documented – see https://github.com/JuliaLang/julia/pull/25141 for workarounds)

1 Like

Thanks! What I really want to do is having a function with a few methods and each method should have some private state. If a method gets overwritten, the state should be garbage collected (or at least some empty! like function should run on it. The application I have in mind is memoization. Is there currently a way to do this?