From dd6ff0dd1c877ca09401a6e608599cf652b90b90 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 20 Jun 2024 05:54:01 +0000 Subject: [PATCH 1/5] Track `GlobalRef` consistently Companion PR to https://github.com/JuliaDebug/LoweredCodeUtils.jl/pull/107. With both of these and https://github.com/JuliaDebug/JuliaInterpreter.jl/pull/634, basic Revise functionality is working for me again on Julia master. --- src/lowered.jl | 33 +++++++++++++++++++++------------ src/parsing.jl | 2 +- src/utils.jl | 5 +++-- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/lowered.jl b/src/lowered.jl index 799c3989..5817dae0 100644 --- a/src/lowered.jl +++ b/src/lowered.jl @@ -85,10 +85,10 @@ Since the contents of such expression are difficult to analyze, it is generally safest to execute all such evals. """ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, src::Core.CodeInfo, mode::Symbol) - edges = CodeEdges(src) + edges = CodeEdges(mod, src) # LoweredCodeUtils.print_with_code(stdout, src, edges) isrequired = fill(false, length(src.code)) - namedconstassigned = Dict{Symbol,Bool}() + namedconstassigned = Dict{GlobalRef,Bool}() evalassign = false for (i, stmt) in enumerate(src.code) if !isrequired[i] @@ -99,18 +99,24 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, end end if isexpr(stmt, :const) - name = stmt.args[1]::Symbol - namedconstassigned[name] = false + name = stmt.args[1] + if isa(name, Symbol) + name = GlobalRef(mod, name) + end + namedconstassigned[name::GlobalRef] = false elseif isexpr(stmt, :(=)) lhs = (stmt::Expr).args[1] if isa(lhs, Symbol) + lhs = GlobalRef(mod, name) + end + if isa(lhs, GlobalRef) if haskey(namedconstassigned, lhs) namedconstassigned[lhs] = true end end if mode === :evalassign evalassign = isrequired[i] = true - if isa(lhs, Symbol) + if isa(lhs, GlobalRef) isrequired[edges.byname[lhs].succs] .= true # mark any `const` statements or other "uses" in this block end end @@ -119,7 +125,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, if mode === :sigs for (name, isassigned) in namedconstassigned isassigned || continue - if isdefined(mod, name) + if isdefined(name.mod, name.name) empty!(edges.byname[name].succs) # avoid redefining `consts` in `:sigs` mode (fixes #789) end end @@ -225,7 +231,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod Core.eval(mod, ex) catch err (always_rethrow || isa(err, InterruptException)) && rethrow(err) - loc = location_string(whereis(frame)...) + loc = location_string(whereis(frame)) bt = trim_toplevel!(catch_backtrace()) throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)])) end @@ -248,7 +254,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod methods_by_execution!(recurse, methodinfo, docexprs, frame, isrequired; mode=mode, kwargs...) catch err (always_rethrow || isa(err, InterruptException)) && (disablebp && foreach(enable, active_bp_refs); rethrow(err)) - loc = location_string(whereis(frame)...) + loc = location_string(whereis(frame)) sfs = [] # crafted for interaction with Base.show_backtrace frame = JuliaInterpreter.leaf(frame) while frame !== nothing @@ -309,10 +315,13 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra # However, it might have been followed by a thunk that defined a # method (issue #435), so we still need to check for additions. if !isempty(signatures) - file, line = whereis(frame.framecode, pc) - lnn = LineNumberNode(Int(line), Symbol(file)) - for sig in signatures - add_signature!(methodinfo, sig, lnn) + loc = whereis(frame.framecode, pc) + if loc !== nothing + file, line = loc + lnn = LineNumberNode(Int(line), Symbol(file)) + for sig in signatures + add_signature!(methodinfo, sig, lnn) + end end end pc = next_or_nothing!(frame) diff --git a/src/parsing.jl b/src/parsing.jl index 313bdf1b..8a8175ea 100644 --- a/src/parsing.jl +++ b/src/parsing.jl @@ -58,7 +58,7 @@ function process_source!(mod_exprs_sigs::ModuleExprsSigs, ex, filename, mod::Mod catch err bt = trim_toplevel!(catch_backtrace()) lnn = firstline(ex) - loc = location_string(lnn.file, lnn.line) + loc = location_string((lnn.file, lnn.line)) throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)])) end end diff --git a/src/utils.jl b/src/utils.jl index 6767ba10..cdfc3be1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -59,8 +59,9 @@ firstline(rex::RelocatableExpr) = firstline(rex.ex) newloc(methloc::LineNumberNode, ln, lno) = fixpath(ln) -location_string(file::AbstractString, line) = abspath(file)*':'*string(line) -location_string(file::Symbol, line) = location_string(string(file), line) +location_string((file, line)::Tuple{AbstractString, Any},) = abspath(file)*':'*string(line) +location_string((file, line)::Tuple{Symbol, Any},) = location_string(string(file), line) +location_string(::Nothing) = "unknown location" function linediff(la::LineNumberNode, lb::LineNumberNode) (isa(la.file, Symbol) && isa(lb.file, Symbol) && (la.file::Symbol === lb.file::Symbol)) || return typemax(Int) From fdae537dc49e431efdbfd6411d29cdab7767a3f6 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 21 Jul 2024 16:25:37 -0500 Subject: [PATCH 2/5] Small fixes --- src/lowered.jl | 2 +- src/utils.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lowered.jl b/src/lowered.jl index 5817dae0..90ce8a34 100644 --- a/src/lowered.jl +++ b/src/lowered.jl @@ -107,7 +107,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, elseif isexpr(stmt, :(=)) lhs = (stmt::Expr).args[1] if isa(lhs, Symbol) - lhs = GlobalRef(mod, name) + lhs = GlobalRef(mod, lhs) end if isa(lhs, GlobalRef) if haskey(namedconstassigned, lhs) diff --git a/src/utils.jl b/src/utils.jl index cdfc3be1..4d65d81b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -60,7 +60,7 @@ firstline(rex::RelocatableExpr) = firstline(rex.ex) newloc(methloc::LineNumberNode, ln, lno) = fixpath(ln) location_string((file, line)::Tuple{AbstractString, Any},) = abspath(file)*':'*string(line) -location_string((file, line)::Tuple{Symbol, Any},) = location_string(string(file), line) +location_string((file, line)::Tuple{Symbol, Any},) = location_string((string(file), line)) location_string(::Nothing) = "unknown location" function linediff(la::LineNumberNode, lb::LineNumberNode) From 37392d748de152309c45751bbbab08df339af642 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 21 Jul 2024 16:30:48 -0500 Subject: [PATCH 3/5] Test `pre`-release --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38f7434d..50eb82d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: - '1.6' # LTS - '1.9' # parsing errors branch on 1.10, so test the last pre-1.10 version - '1' # current stable + - 'pre' # next release, if available os: - ubuntu-latest - macOS-latest From f6d9cfb9c93e9f443d90ce6462a9a46fe8b067b7 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 23 Jul 2024 11:17:16 +0000 Subject: [PATCH 4/5] Catch more assignment locations --- src/lowered.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lowered.jl b/src/lowered.jl index 90ce8a34..97546915 100644 --- a/src/lowered.jl +++ b/src/lowered.jl @@ -104,7 +104,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, name = GlobalRef(mod, name) end namedconstassigned[name::GlobalRef] = false - elseif isexpr(stmt, :(=)) + elseif LoweredCodeUtils.is_assignment_like(stmt) lhs = (stmt::Expr).args[1] if isa(lhs, Symbol) lhs = GlobalRef(mod, lhs) @@ -283,7 +283,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra while true JuliaInterpreter.is_leaf(frame) || (@warn("not a leaf"); break) stmt = pc_expr(frame, pc) - if !isrequired[pc] && mode !== :eval && !(mode === :evalassign && isexpr(stmt, :(=))) + if !isrequired[pc] && mode !== :eval && !(mode === :evalassign && LoweredCodeUtils.is_assignment_like(stmt)) pc = next_or_nothing!(frame) pc === nothing && break continue @@ -409,7 +409,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra end end end - elseif head === :(=) + elseif LoweredCodeUtils.is_assignment_like(stmt) # If we're here, either isrequired[pc] is true, or the mode forces us to eval assignments pc = step_expr!(recurse, frame, stmt, true) elseif head === :call From 04636d9bb9c2067ba9bb5f7c37cf882ea166e142 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 23 Jul 2024 14:54:58 -0500 Subject: [PATCH 5/5] Require LCU 3 --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index fac557cd..010d9dd1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Revise" uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "3.5.15" +version = "3.5.16" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" @@ -19,7 +19,7 @@ Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [compat] CodeTracking = "1.2" JuliaInterpreter = "0.9" -LoweredCodeUtils = "2.3" +LoweredCodeUtils = "3" OrderedCollections = "1" # Exclude Requires-1.1.0 - see https://github.com/JuliaPackaging/Requires.jl/issues/94 Requires = "~1.0, ^1.1.1"