Skip to content

Commit c8fb669

Browse files
authored
Focus running-name lookup on just the caller (#45)
Fixes timholy/Revise.jl#420
1 parent 5d28c19 commit c8fb669

File tree

4 files changed

+21
-29
lines changed

4 files changed

+21
-29
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "LoweredCodeUtils"
22
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
33
authors = ["Tim Holy <[email protected]>"]
4-
version = "1.2.1"
4+
version = "1.2.2"
55

66
[deps]
77
JuliaInterpreter = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"

docs/src/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ LoweredCodeUtils.MethodInfo
2929
LoweredCodeUtils.identify_framemethod_calls
3030
LoweredCodeUtils.iscallto
3131
LoweredCodeUtils.getcallee
32-
LoweredCodeUtils.find_corrected_name
32+
LoweredCodeUtils.find_name_caller_sig
3333
LoweredCodeUtils.replacename!
3434
LoweredCodeUtils.Variable
3535
```

src/signatures.jl

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ to methods defined in `frame` that occur within `frame`.
121121
122122
`methodinfos` is a Dict of `name=>info` pairs, where `info` is a [`MethodInfo`](@ref).
123123
124-
`selfcalls` is a list of `(linetop, linebody, callee, caller)` tuples that holds the location of
124+
`selfcalls` is a list of `SelfCall(linetop, linebody, callee, caller)` that holds the location of
125125
calls the methods defined in `frame`. `linetop` is the line in `frame` (top meaning "top level"),
126126
which will correspond to a 3-argument `:method` expression containing a `CodeInfo` body.
127127
`linebody` is the line within the `CodeInfo` body from which the call is made.
@@ -223,26 +223,27 @@ function callchain(selfcalls)
223223
return calledby
224224
end
225225

226-
function set_to_running_name!(@nospecialize(recurse), replacements, frame, methodinfos, calledby, callee, caller)
226+
function set_to_running_name!(@nospecialize(recurse), replacements, frame, methodinfos, selfcall, calledby, callee, caller)
227227
if isa(caller, Symbol) && startswith(String(caller), '#')
228228
rep = get(replacements, caller, nothing)
229229
if rep === nothing
230230
parentcaller = get(calledby, caller, nothing)
231231
if parentcaller !== nothing
232-
set_to_running_name!(recurse, replacements, frame, methodinfos, calledby, caller, parentcaller)
232+
set_to_running_name!(recurse, replacements, frame, methodinfos, selfcall, calledby, caller, parentcaller)
233233
end
234234
else
235235
caller = rep
236236
end
237237
end
238-
if isa(caller, Symbol)
239-
mi = methodinfos[caller]
240-
cname, _pc, _ = get_running_name(recurse, frame, mi.start, callee, get(replacements, caller, caller))
241-
else
242-
# For generated constructors (which have no name), we just assume they immediately follow their callee
243-
mi = methodinfos[callee]
244-
cname, _pc, _ = get_running_name(recurse, frame, mi.stop+1, callee, get(replacements, caller, caller))
238+
# Back up to the beginning of the signature
239+
pc = selfcall.linetop
240+
stmt = pc_expr(frame, pc)
241+
while pc > 1 && !ismethod1(stmt)
242+
pc -= 1
243+
stmt = pc_expr(frame, pc)
245244
end
245+
@assert ismethod1(stmt)
246+
cname, _pc, _ = get_running_name(recurse, frame, pc+1, callee, get(replacements, caller, caller))
246247
replacements[callee] = cname
247248
mi = methodinfos[cname] = methodinfos[callee]
248249
src = frame.framecode.src
@@ -270,8 +271,10 @@ function rename_framemethods!(@nospecialize(recurse), frame::Frame, methodinfos,
270271
replacements = Dict{Symbol,Symbol}()
271272
for (callee, caller) in calledby
272273
(!startswith(String(callee), '#') || haskey(replacements, callee)) && continue
274+
idx = findfirst(sc->sc.callee === callee && sc.caller === caller, selfcalls)
275+
idx === nothing && continue
273276
try
274-
set_to_running_name!(recurse, replacements, frame, methodinfos, calledby, callee, caller)
277+
set_to_running_name!(recurse, replacements, frame, methodinfos, selfcalls[idx], calledby, callee, caller)
275278
catch err
276279
@warn "skipping callee $callee (called by $caller) due to $err"
277280
end
@@ -297,7 +300,7 @@ end
297300
rename_framemethods!(frame::Frame) = rename_framemethods!(finish_and_return!, frame)
298301

299302
"""
300-
pctop, isgen = find_corrected_name(recurse, frame, pc, name, parentname)
303+
pctop, isgen = find_name_caller_sig(recurse, frame, pc, name, parentname)
301304
302305
Scans forward from `pc` in `frame` until a method is found that calls `name`.
303306
`pctop` points to the beginning of that method's signature.
@@ -306,7 +309,7 @@ Scans forward from `pc` in `frame` until a method is found that calls `name`.
306309
Alternatively, this returns `nothing` if `pc` does not appear to point to either
307310
a keyword or generated method.
308311
"""
309-
function find_corrected_name(@nospecialize(recurse), frame, pc, name, parentname)
312+
function find_name_caller_sig(@nospecialize(recurse), frame, pc, name, parentname)
310313
stmt = pc_expr(frame, pc)
311314
while true
312315
pc0 = pc
@@ -316,18 +319,6 @@ function find_corrected_name(@nospecialize(recurse), frame, pc, name, parentname
316319
stmt = pc_expr(frame, pc)
317320
end
318321
body = stmt.args[3]
319-
if stmt.args[1] !== name && isa(body, SSAValue)
320-
# OK, we can't skip all the stuff that might define the body
321-
# See https://github.com/timholy/Revise.jl/issues/398
322-
pc = pc0
323-
stmt = pc_expr(frame, pc)
324-
while !ismethod3(stmt)
325-
pc = step_expr!(recurse, frame, stmt, true)
326-
pc === nothing && return nothing
327-
stmt = pc_expr(frame, pc)
328-
end
329-
body = @lookup(frame, stmt.args[3])
330-
end
331322
if stmt.args[1] !== name && isa(body, CodeInfo)
332323
# This might be the GeneratedFunctionStub for a @generated method
333324
for (i, bodystmt) in enumerate(body.code)
@@ -379,8 +370,7 @@ function replacename!(args::Vector{Any}, pr)
379370
end
380371

381372
function get_running_name(@nospecialize(recurse), frame, pc, name, parentname)
382-
# Get the correct name (the one that's actively running)
383-
nameinfo = find_corrected_name(recurse, frame, pc, name, parentname)
373+
nameinfo = find_name_caller_sig(recurse, frame, pc, name, parentname)
384374
if nameinfo === nothing
385375
pc = skip_until(stmt->isexpr(stmt, :method, 3), frame, pc)
386376
pc = next_or_nothing(frame, pc)

test/signatures.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ bodymethtest5(x, y=Dict(1=>2)) = 5
350350
@test length(ks) == 2
351351
@test dct[ks[1]] == dct[ks[2]]
352352
@test isdefined(Lowering, ks[1]) || isdefined(Lowering, ks[2])
353+
nms = filter(sym->occursin(r"#Items#\d+#\d+", String(sym)), names(Lowering; all=true))
354+
@test length(nms) == 1
353355

354356
# https://github.com/timholy/Revise.jl/issues/422
355357
ex = :(@generated function fneg(x::T) where T<:LT{<:FloatingTypes}

0 commit comments

Comments
 (0)