Skip to content

Commit 4ad68c2

Browse files
Kenotimholy
andauthored
Track GlobalRef consistently (#822)
Companion PR to JuliaDebug/LoweredCodeUtils.jl#107. With both of these and JuliaDebug/JuliaInterpreter.jl#634, basic Revise functionality is working for me again on Julia master. However, tests are still failing, so there will be more work needed for full functionality. Co-authored-by: Tim Holy <[email protected]>
1 parent 54ee94a commit 4ad68c2

File tree

5 files changed

+31
-20
lines changed

5 files changed

+31
-20
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
- '1.6' # LTS
1818
- '1.9' # parsing errors branch on 1.10, so test the last pre-1.10 version
1919
- '1' # current stable
20+
- 'pre' # next release, if available
2021
os:
2122
- ubuntu-latest
2223
- macOS-latest

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Revise"
22
uuid = "295af30f-e4ad-537b-8983-00126c2a3abe"
3-
version = "3.5.15"
3+
version = "3.5.16"
44

55
[deps]
66
CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
@@ -19,7 +19,7 @@ Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
1919
[compat]
2020
CodeTracking = "1.2"
2121
JuliaInterpreter = "0.9"
22-
LoweredCodeUtils = "2.3"
22+
LoweredCodeUtils = "3"
2323
OrderedCollections = "1"
2424
# Exclude Requires-1.1.0 - see https://github.com/JuliaPackaging/Requires.jl/issues/94
2525
Requires = "~1.0, ^1.1.1"

src/lowered.jl

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ Since the contents of such expression are difficult to analyze, it is generally
8585
safest to execute all such evals.
8686
"""
8787
function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, src::Core.CodeInfo, mode::Symbol)
88-
edges = CodeEdges(src)
88+
edges = CodeEdges(mod, src)
8989
# LoweredCodeUtils.print_with_code(stdout, src, edges)
9090
isrequired = fill(false, length(src.code))
91-
namedconstassigned = Dict{Symbol,Bool}()
91+
namedconstassigned = Dict{GlobalRef,Bool}()
9292
evalassign = false
9393
for (i, stmt) in enumerate(src.code)
9494
if !isrequired[i]
@@ -99,18 +99,24 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module,
9999
end
100100
end
101101
if isexpr(stmt, :const)
102-
name = stmt.args[1]::Symbol
103-
namedconstassigned[name] = false
104-
elseif isexpr(stmt, :(=))
102+
name = stmt.args[1]
103+
if isa(name, Symbol)
104+
name = GlobalRef(mod, name)
105+
end
106+
namedconstassigned[name::GlobalRef] = false
107+
elseif LoweredCodeUtils.is_assignment_like(stmt)
105108
lhs = (stmt::Expr).args[1]
106109
if isa(lhs, Symbol)
110+
lhs = GlobalRef(mod, lhs)
111+
end
112+
if isa(lhs, GlobalRef)
107113
if haskey(namedconstassigned, lhs)
108114
namedconstassigned[lhs] = true
109115
end
110116
end
111117
if mode === :evalassign
112118
evalassign = isrequired[i] = true
113-
if isa(lhs, Symbol)
119+
if isa(lhs, GlobalRef)
114120
isrequired[edges.byname[lhs].succs] .= true # mark any `const` statements or other "uses" in this block
115121
end
116122
end
@@ -119,7 +125,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module,
119125
if mode === :sigs
120126
for (name, isassigned) in namedconstassigned
121127
isassigned || continue
122-
if isdefined(mod, name)
128+
if isdefined(name.mod, name.name)
123129
empty!(edges.byname[name].succs) # avoid redefining `consts` in `:sigs` mode (fixes #789)
124130
end
125131
end
@@ -225,7 +231,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
225231
Core.eval(mod, ex)
226232
catch err
227233
(always_rethrow || isa(err, InterruptException)) && rethrow(err)
228-
loc = location_string(whereis(frame)...)
234+
loc = location_string(whereis(frame))
229235
bt = trim_toplevel!(catch_backtrace())
230236
throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)]))
231237
end
@@ -248,7 +254,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
248254
methods_by_execution!(recurse, methodinfo, docexprs, frame, isrequired; mode=mode, kwargs...)
249255
catch err
250256
(always_rethrow || isa(err, InterruptException)) && (disablebp && foreach(enable, active_bp_refs); rethrow(err))
251-
loc = location_string(whereis(frame)...)
257+
loc = location_string(whereis(frame))
252258
sfs = [] # crafted for interaction with Base.show_backtrace
253259
frame = JuliaInterpreter.leaf(frame)
254260
while frame !== nothing
@@ -277,7 +283,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
277283
while true
278284
JuliaInterpreter.is_leaf(frame) || (@warn("not a leaf"); break)
279285
stmt = pc_expr(frame, pc)
280-
if !isrequired[pc] && mode !== :eval && !(mode === :evalassign && isexpr(stmt, :(=)))
286+
if !isrequired[pc] && mode !== :eval && !(mode === :evalassign && LoweredCodeUtils.is_assignment_like(stmt))
281287
pc = next_or_nothing!(frame)
282288
pc === nothing && break
283289
continue
@@ -309,10 +315,13 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
309315
# However, it might have been followed by a thunk that defined a
310316
# method (issue #435), so we still need to check for additions.
311317
if !isempty(signatures)
312-
file, line = whereis(frame.framecode, pc)
313-
lnn = LineNumberNode(Int(line), Symbol(file))
314-
for sig in signatures
315-
add_signature!(methodinfo, sig, lnn)
318+
loc = whereis(frame.framecode, pc)
319+
if loc !== nothing
320+
file, line = loc
321+
lnn = LineNumberNode(Int(line), Symbol(file))
322+
for sig in signatures
323+
add_signature!(methodinfo, sig, lnn)
324+
end
316325
end
317326
end
318327
pc = next_or_nothing!(frame)
@@ -400,7 +409,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
400409
end
401410
end
402411
end
403-
elseif head === :(=)
412+
elseif LoweredCodeUtils.is_assignment_like(stmt)
404413
# If we're here, either isrequired[pc] is true, or the mode forces us to eval assignments
405414
pc = step_expr!(recurse, frame, stmt, true)
406415
elseif head === :call

src/parsing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function process_source!(mod_exprs_sigs::ModuleExprsSigs, ex, filename, mod::Mod
5858
catch err
5959
bt = trim_toplevel!(catch_backtrace())
6060
lnn = firstline(ex)
61-
loc = location_string(lnn.file, lnn.line)
61+
loc = location_string((lnn.file, lnn.line))
6262
throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)]))
6363
end
6464
end

src/utils.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ firstline(rex::RelocatableExpr) = firstline(rex.ex)
5959

6060
newloc(methloc::LineNumberNode, ln, lno) = fixpath(ln)
6161

62-
location_string(file::AbstractString, line) = abspath(file)*':'*string(line)
63-
location_string(file::Symbol, line) = location_string(string(file), line)
62+
location_string((file, line)::Tuple{AbstractString, Any},) = abspath(file)*':'*string(line)
63+
location_string((file, line)::Tuple{Symbol, Any},) = location_string((string(file), line))
64+
location_string(::Nothing) = "unknown location"
6465

6566
function linediff(la::LineNumberNode, lb::LineNumberNode)
6667
(isa(la.file, Symbol) && isa(lb.file, Symbol) && (la.file::Symbol === lb.file::Symbol)) || return typemax(Int)

0 commit comments

Comments
 (0)