Skip to content

Commit 9272cba

Browse files
authored
Eval thunks that create methods (#794)
Fixes #792
1 parent 1ea6980 commit 9272cba

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

src/lowered.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,25 @@ function categorize_stmt(@nospecialize(stmt))
5454
ismeth, haseval, isinclude, isnamespace, istoplevel = false, false, false, false, false
5555
if isa(stmt, Expr)
5656
haseval = matches_eval(stmt)
57-
ismeth = stmt.head === :method
57+
ismeth = stmt.head === :method || (stmt.head === :thunk && defines_function(only(stmt.args)))
5858
istoplevel = stmt.head === :toplevel
5959
isnamespace = stmt.head === :export || stmt.head === :import || stmt.head === :using
6060
isinclude = stmt.head === :call && stmt.args[1] === :include
6161
end
6262
return ismeth, haseval, isinclude, isnamespace, istoplevel
6363
end
64+
# Check for thunks that define functions (fixes #792)
65+
function defines_function(ci)
66+
isa(ci, CodeInfo) || return false
67+
if length(ci.code) == 1
68+
stmt = ci.code[1]
69+
if isa(stmt, Core.ReturnNode)
70+
val = stmt.val
71+
isexpr(val, :method) && return true
72+
end
73+
end
74+
return false
75+
end
6476

6577
"""
6678
isrequired, evalassign = minimal_evaluation!([predicate,] methodinfo, src::Core.CodeInfo, mode::Symbol)
@@ -280,6 +292,9 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
280292
end
281293
isassign(frame, pc) && assign_this!(frame, value)
282294
pc = next_or_nothing!(frame)
295+
elseif head === :thunk && defines_function(only(stmt.args))
296+
mode !== :sigs && Core.eval(mod, stmt)
297+
pc = next_or_nothing!(frame)
283298
# elseif head === :thunk && isanonymous_typedef(stmt.args[1])
284299
# # Anonymous functions should just be defined anew, since there does not seem to be a practical
285300
# # way to find them within the already-defined module.
@@ -300,7 +315,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
300315
add_signature!(methodinfo, sig, lnn)
301316
end
302317
end
303-
pc += 1
318+
pc = next_or_nothing!(frame)
304319
else
305320
pc, pc3 = ret
306321
# Get the line number from the body

test/backedges.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ do_test("Backedges") && @testset "Backedges" begin
1717
src2 = src.code[idtype].args[1]
1818
methodinfo = Revise.MethodInfo()
1919
isrequired = Revise.minimal_evaluation!(methodinfo, frame, :sigs)[1]
20-
@test sum(isrequired) == length(src.code)-2 # skips the `return` at the end
20+
@test sum(isrequired) == length(src.code)-1 # skips the `return` at the end
2121

2222
src = """
2323
# issue #249

test/runtests.jl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ using Base.CoreLogging: Debug,Info
1515
using Revise.CodeTracking: line_is_decl
1616

1717
# In addition to using this for the "More arg-modifying macros" test below,
18-
# this package is used on Travis to test what happens when you have multiple
18+
# this package is used on CI to test what happens when you have multiple
1919
# *.ji files for the package.
2020
using EponymTuples
2121

@@ -41,6 +41,12 @@ macro addint(ex)
4141
:($(esc(ex))::$(esc(Int)))
4242
end
4343

44+
macro empty_function(name)
45+
return esc(quote
46+
function $name end
47+
end)
48+
end
49+
4450
# The following two submodules are for testing #199
4551
module A
4652
f(x::Int) = 1
@@ -1409,6 +1415,20 @@ const issue639report = []
14091415
@test MacroLineNos568.my_fun() == 30
14101416
rm_precompile("MacroLineNos568")
14111417

1418+
# Macros that create empty functions (another macro *execution* bug, issue #792)
1419+
file = tempname()
1420+
write(file, "@empty_function issue792f1\n")
1421+
sleep(mtimedelay)
1422+
includet(ReviseTestPrivate, file)
1423+
sleep(mtimedelay)
1424+
@test isempty(methods(ReviseTestPrivate.issue792f1))
1425+
open(file, "a") do f
1426+
println(f, "@empty_function issue792f2")
1427+
end
1428+
yry()
1429+
@test isempty(methods(ReviseTestPrivate.issue792f2))
1430+
rm(file)
1431+
14121432
pop!(LOAD_PATH)
14131433
end
14141434

0 commit comments

Comments
 (0)