Skip to content

Commit 2a4cf89

Browse files
authored
Try harder to find __toplevel__ stdlibs in ExprSplitter (#447)
Revise has to be able to analyze code in modules that are not in the namespace. It turns out that differences between how discovery works in interactive mode (which implicitly widens the Manifest to include all the stdlibs) and test-mode (which does not) have led to the handling discovery of toplevel modules problematic for some time: it turns out we've been constructing "shadow" modules of the same names as these stdlibs. Some of the exclusions in Revise's `sigtest.jl` test file reflect this. This causes ExprSplitter to try harder to find modules from `Base.__toplevel__`. When we can't resolve the name in the manifest, we also check Base.loaded_modules and see if we can find something of that name. This fixes a bug that just manifested (but whose roots are old) for Revise on nightly.
1 parent 86da367 commit 2a4cf89

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/construct.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,19 @@ function queuenext!(iter::ExprSplitter)
483483
newmod isa Module || throw(ErrorException("invalid redefinition of constant $(newname)"))
484484
mod = newmod
485485
else
486-
if (id = Base.identify_package(mod, String(newname))) !== nothing && haskey(Base.loaded_modules, id)
486+
newnamestr = String(newname)
487+
id = Base.identify_package(mod, newnamestr)
488+
# If we're in a test environment and Julia's internal stdlibs are not a declared dependency of the package,
489+
# we might fail to find it. Try really hard to find it.
490+
if id === nothing && mod === Base.__toplevel__
491+
for loaded_id in keys(Base.loaded_modules)
492+
if loaded_id.name == newnamestr
493+
id = loaded_id
494+
break
495+
end
496+
end
497+
end
498+
if id !== nothing && haskey(Base.loaded_modules, id)
487499
mod = Base.root_module(id)::Module
488500
else
489501
loc = firstline(ex)

test/toplevel.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,28 @@ module Namespace end
251251
Core.eval(Base, :(sin(x::Int) = sin(float(x)))) # fix the definition of `sin`
252252
end
253253
end
254+
# When retrospectively parsing through modules to analyze code, Julia's stdlibs pose a bit
255+
# of a namespace challenge too: we never want to redefine new modules with the same name.
256+
@testset "Namespace stdlibs" begin
257+
# Get the "real" LibCURL_jll module (Julia 1.6 and higher)
258+
modref = nothing
259+
for (id, mod) in Base.loaded_modules
260+
if id.name == "LibCURL_jll"
261+
modref = mod
262+
break
263+
end
264+
end
265+
if modref !== nothing
266+
# Now try to find it by splitting
267+
exsplit = JuliaInterpreter.ExprSplitter(Base.__toplevel__, :(
268+
baremodule LibCURL_jll
269+
using Base
270+
Base.Experimental.@compiler_options compile=min optimize=0 infer=false
271+
end))
272+
(mod1, ex1), state1 = iterate(exsplit)
273+
@test mod1 === modref
274+
end
275+
end
254276

255277
# incremental interpretation solves world-age problems
256278
# Taken straight from Julia's test/tuple.jl

0 commit comments

Comments
 (0)