Skip to content

Commit

Permalink
More 1.12 compat (#827)
Browse files Browse the repository at this point in the history
* More 1.12 compat

With this and the LCU fixes, Revise should pass tests again on 1.12.

* Bump LCU

* handle change in Base.active_repl_backend on 1.12

* Fix Methods at REPL test on CI

* Stop trying to be clever

---------

Co-authored-by: Ian Butterworth <[email protected]>
  • Loading branch information
Keno and IanButterworth authored Jul 28, 2024
1 parent b596f03 commit 758d5fd
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 21 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ jobs:
echo "Methods at REPL"
TERM="xterm" julia --project --code-coverage=user -e '
using InteractiveUtils, REPL, Revise
@async(Base.run_main_repl(true, true, false, true, false))
while !isdefined(Base, :active_repl_backend) sleep(0.1) end
t = @async(
VERSION >= v"1.12.0-DEV.612" ? Base.run_main_repl(true, true, :no, true) :
VERSION >= v"1.11.0-DEV.222" ? Base.run_main_repl(true, true, :no, true, false) :
Base.run_main_repl(true, true, false, true, false))
isdefined(Base, :errormonitor) && Base.errormonitor(t)
while (!isdefined(Base, :active_repl_backend) || isnothing(Base.active_repl_backend)) sleep(0.1) end
pushfirst!(Base.active_repl_backend.ast_transforms, Revise.revise_first)
include(joinpath("test", "runtests.jl"))
if Base.VERSION.major == 1 && Base.VERSION.minor >= 9
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[compat]
CodeTracking = "1.2"
JuliaInterpreter = "0.9"
LoweredCodeUtils = "3"
LoweredCodeUtils = "3.0.1"
OrderedCollections = "1"
# Exclude Requires-1.1.0 - see https://github.com/JuliaPackaging/Requires.jl/issues/94
Requires = "~1.0, ^1.1.1"
Expand Down
30 changes: 21 additions & 9 deletions src/loading.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
const badfile = (nothing, nothing, nothing, UInt128(0))
function pkg_fileinfo(id::PkgId)
origin = get(Base.pkgorigins, id, nothing)
origin === nothing && return nothing, nothing, nothing
origin === nothing && return badfile
cachepath = origin.cachepath
cachepath === nothing && return nothing, nothing, nothing
cachepath === nothing && return badfile
local checksum
provides, includes_requires, required_modules = try
@static if VERSION v"1.11.0-DEV.683" # https://github.com/JuliaLang/julia/pull/49866
ret = @static if VERSION v"1.11.0-DEV.683" # https://github.com/JuliaLang/julia/pull/49866
io = open(cachepath, "r")
checksum = Base.isvalid_cache_header(io)
iszero(checksum) && (close(io); return badfile)
provides, (_, includes_srcfiles_only, requires), required_modules, _... =
Base.parse_cache_header(cachepath)
Base.parse_cache_header(io, cachepath)
close(io)
provides, (includes_srcfiles_only, requires), required_modules
else
checksum = UInt64(0) # Buildid prior to v"1.12.0-DEV.764", and the `srcfiles_only` API does not take `io`
Base.parse_cache_header(cachepath, srcfiles_only = true)
end
catch
return nothing, nothing, nothing
ret
catch err
return badfile
end
includes, _ = includes_requires
for (pkgid, buildid) in provides
if pkgid.uuid === id.uuid && pkgid.name == id.name
return cachepath, includes, first.(required_modules)
return cachepath, includes, first.(required_modules), (UInt128(checksum) << 64 | buildid)
end
end
end
Expand All @@ -29,13 +37,17 @@ function parse_pkg_files(id::PkgId)
end
modsym = Symbol(id.name)
if use_compiled_modules()
cachefile, includes, reqs = pkg_fileinfo(id)
cachefile, includes, reqs, buildid = pkg_fileinfo(id)
if cachefile !== nothing
@assert includes !== nothing
@assert reqs !== nothing
pkgdata.requirements = reqs
for chi in includes
mod = Base.root_module(id)
if VERSION >= v"1.12.0-DEV.764" && haskey(Base.loaded_precompiles, id => buildid)
mod = Base.loaded_precompiles[id => buildid]
else
mod = Base.root_module(id)
end
for mpath in chi.modpath
mod = getfield(mod, Symbol(mpath))::Module
end
Expand Down
21 changes: 19 additions & 2 deletions src/lowered.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ pop_expr!(methodinfo::MethodInfo) = methodinfo
add_dependencies!(methodinfo::MethodInfo, be::CodeEdges, src, isrequired) = methodinfo
add_includes!(methodinfo::MethodInfo, mod::Module, filename) = methodinfo

function is_some_include(@nospecialize(f))
if isa(f, GlobalRef)
return f.name === :include
elseif isa(f, Symbol)
return f === :include
else
if isa(f, QuoteNode)
f = f.value
end
if isa(f, Function)
mod = Base.typename(typeof(f)).module
return isdefined(mod, :include) && f === (@isdefined(getglobal) ? getglobal(mod, :include) : getfield(mod, :include))
end
end
return false
end

# This is not generally used, see `is_method_or_eval` instead
function hastrackedexpr(stmt; heads=LoweredCodeUtils.trackedheads)
haseval = false
Expand All @@ -32,7 +49,7 @@ function hastrackedexpr(stmt; heads=LoweredCodeUtils.trackedheads)
f = stmt.args[1]
callee_matches(f, Core, :_typebody!) && return true, haseval
callee_matches(f, Core, :_setsuper!) && return true, haseval
f === :include && return true, haseval
is_some_include(f) && return true, haseval
elseif stmt.head === :thunk
any(s->any(hastrackedexpr(s; heads=heads)), (stmt.args[1]::Core.CodeInfo).code) && return true, haseval
elseif stmt.head heads
Expand All @@ -57,7 +74,7 @@ function categorize_stmt(@nospecialize(stmt))
ismeth = stmt.head === :method || (stmt.head === :thunk && defines_function(only(stmt.args)))
istoplevel = stmt.head === :toplevel
isnamespace = stmt.head === :export || stmt.head === :import || stmt.head === :using
isinclude = stmt.head === :call && stmt.args[1] === :include
isinclude = stmt.head === :call && is_some_include(stmt.args[1])
end
return ismeth, haseval, isinclude, isnamespace, istoplevel
end
Expand Down
10 changes: 6 additions & 4 deletions src/packagedef.jl
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ function revise(mod::Module)
for def in keys(exsigs)
ex = def.ex
exuw = unwrap(ex)
isexpr(exuw, :call) && exuw.args[1] === :include && continue
isexpr(exuw, :call) && is_some_include(exuw.args[1]) && continue
try
Core.eval(mod, ex)
catch err
Expand Down Expand Up @@ -1266,6 +1266,8 @@ function init_worker(p)
end)
end

active_repl_backend_available() = isdefined(Base, :active_repl_backend) && Base.active_repl_backend !== nothing

function __init__()
ccall(:jl_generating_output, Cint, ()) == 1 && return nothing
run_on_worker = get(ENV, "JULIA_REVISE_WORKER_ONLY", "0")
Expand Down Expand Up @@ -1327,18 +1329,18 @@ function __init__()
else
pushfirst!(REPL.repl_ast_transforms, revise_first)
# #664: once a REPL is started, it no longer interacts with REPL.repl_ast_transforms
if isdefined(Base, :active_repl_backend)
if active_repl_backend_available()
push!(Base.active_repl_backend.ast_transforms, revise_first)
else
# wait for active_repl_backend to exist
# #719: do this async in case Revise is being loaded from startup.jl
t = @async begin
iter = 0
while !isdefined(Base, :active_repl_backend) && iter < 20
while !active_repl_backend_available() && iter < 20
sleep(0.05)
iter += 1
end
if isdefined(Base, :active_repl_backend)
if active_repl_backend_available()
push!(Base.active_repl_backend.ast_transforms, revise_first)
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/pkgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ end
function deferrable_require!(includes, expr::Expr)
if expr.head === :call
callee = expr.args[1]
if callee === :include
if is_some_include(callee)
if isa(expr.args[2], AbstractString)
push!(includes, expr.args[2])
else
Expand Down
1 change: 1 addition & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ task, so a `yield` will need to occur before it happens.
"""
function throwto_repl(e::Exception)
if isdefined(Base, :active_repl_backend) &&
!isnothing(Base.active_repl_backend) &&
Base.active_repl_backend.backend_task.state === :runnable &&
isempty(Base.Workqueue) &&
Base.active_repl_backend.in_eval
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2901,7 +2901,7 @@ const issue639report = []
end

do_test("Methods at REPL") && @testset "Methods at REPL" begin
if isdefined(Base, :active_repl)
if isdefined(Base, :active_repl) && !isnothing(Base.active_repl)
hp = Base.active_repl.interface.modes[1].hist
fstr = "__fREPL__(x::Int16) = 0"
histidx = length(hp.history) + 1 - hp.start_idx
Expand Down
2 changes: 1 addition & 1 deletion test/start_late.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Test

@async(Base.run_main_repl(true, true, false, true, false))
while !isdefined(Base, :active_repl_backend)
while !isdefined(Base, :active_repl_backend) || isnothing(Base.active_repl_backend)
sleep(0.5)
end

Expand Down

0 comments on commit 758d5fd

Please sign in to comment.