Skip to content

Commit 80b900e

Browse files
authored
Support self-referential struct definitions (#283)
Fixes timholy/Revise.jl#304
1 parent cbabccf commit 80b900e

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

src/interpret.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,23 @@ function set_structtype_const(mod::Module, name::Symbol)
294294
end
295295

296296
function evaluate_structtype(@nospecialize(recurse), frame, node)
297+
grsvec!(ex::Expr) = (ex.args[1] = GlobalRef(Core, :svec); return ex)
298+
297299
name, mod = structname(frame, node)
298-
params = lookup_or_eval(recurse, frame, node.args[2])::SimpleVector
299-
fieldnames = lookup_or_eval(recurse, frame, node.args[3])::SimpleVector
300300
supertype = lookup_or_eval(recurse, frame, node.args[4])::Type
301-
fieldtypes = lookup_or_eval(recurse, frame, node.args[5])::SimpleVector
302301
ismutable = node.args[6]
303302
ninit = node.args[7]
304-
Core.eval(mod, Expr(:struct_type, name, params, fieldnames, supertype, fieldtypes, ismutable, ninit))
303+
newstructexpr = Expr(:struct_type, name, nothing, nothing, supertype, nothing, ismutable, ninit)
304+
for idx in (2, 3, 5)
305+
ex = newstructexpr.args[idx] = grsvec!(copy(node.args[idx]))
306+
for i = 2:length(ex.args)
307+
a = ex.args[i]
308+
if isa(a, SSAValue) || isa(a, SlotNumber)
309+
ex.args[i] = lookup_var(frame, a)
310+
end
311+
end
312+
end
313+
Core.eval(mod, newstructexpr)
305314
VERSION < v"1.2.0-DEV.239" && set_structtype_const(mod, name)
306315
end
307316

test/toplevel.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,11 @@ end
391391
@test length(docexprs[Toplevel]) == 2
392392
@test length(docexprs[Toplevel.Sub]) == 1
393393
end
394+
395+
@testset "Self referential" begin
396+
# Revise issue #304
397+
ex = :(mutable struct Node t :: Node end)
398+
frame = JuliaInterpreter.prepare_thunk(Toplevel, ex)
399+
JuliaInterpreter.finish!(frame, true)
400+
@test Toplevel.Node isa Type
401+
end

0 commit comments

Comments
 (0)