Skip to content

Commit

Permalink
improve type stability of Base.active_module() (JuliaLang#45838)
Browse files Browse the repository at this point in the history
Now this method is called from many `show`-related utilities, so it
would be better to make it robust against invalidations.
  • Loading branch information
aviatesk authored and pcjentsch committed Aug 18, 2022
1 parent 32f472a commit 2c5ebe6
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 17 deletions.
4 changes: 4 additions & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ include("operators.jl")
include("pointer.jl")
include("refvalue.jl")
include("refpointer.jl")

# The REPL stdlib hooks into Base using this Ref
const REPL_MODULE_REF = Ref{Module}()

include("checked.jl")
using .Checked

Expand Down
20 changes: 9 additions & 11 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,6 @@ function __atreplinit(repl)
end
_atreplinit(repl) = invokelatest(__atreplinit, repl)

# The REPL stdlib hooks into Base using this Ref
const REPL_MODULE_REF = Ref{Module}()

function load_InteractiveUtils(mod::Module=Main)
# load interactive-only libraries
if !isdefined(mod, :InteractiveUtils)
Expand All @@ -390,10 +387,10 @@ function load_InteractiveUtils(mod::Module=Main)
return getfield(mod, :InteractiveUtils)
end

global active_repl

# run the requested sort of evaluation loop on stdio
function run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
global active_repl

load_InteractiveUtils()

if interactive && isassigned(REPL_MODULE_REF)
Expand All @@ -402,17 +399,18 @@ function run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_fil
term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr)
banner && Base.banner(term)
if term.term_type == "dumb"
active_repl = REPL.BasicREPL(term)
repl = REPL.BasicREPL(term)
quiet || @warn "Terminal not fully functional"
else
active_repl = REPL.LineEditREPL(term, get(stdout, :color, false), true)
active_repl.history_file = history_file
repl = REPL.LineEditREPL(term, get(stdout, :color, false), true)
repl.history_file = history_file
end
global active_repl = repl
# Make sure any displays pushed in .julia/config/startup.jl ends up above the
# REPLDisplay
pushdisplay(REPL.REPLDisplay(active_repl))
_atreplinit(active_repl)
REPL.run_repl(active_repl, backend->(global active_repl_backend = backend))
pushdisplay(REPL.REPLDisplay(repl))
_atreplinit(repl)
REPL.run_repl(repl, backend->(global active_repl_backend = backend))
end
else
# otherwise provide a simple fallback
Expand Down
8 changes: 5 additions & 3 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,11 @@ function _show_default(io::IO, @nospecialize(x))
print(io,')')
end

active_module()::Module = isdefined(Base, :active_repl) && isdefined(Base.active_repl, :mistate) && Base.active_repl.mistate !== nothing ?
Base.active_repl.mistate.active_module :
Main
function active_module()
isassigned(REPL_MODULE_REF) || return Main
REPL = REPL_MODULE_REF[]
return REPL.active_module()::Module
end

# Check if a particular symbol is exported from a standard library module
function is_exported_from_stdlib(name::Symbol, mod::Module)
Expand Down
13 changes: 10 additions & 3 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -491,21 +491,28 @@ REPLCompletionProvider() = REPLCompletionProvider(LineEdit.Modifiers())
mutable struct ShellCompletionProvider <: CompletionProvider end
struct LatexCompletions <: CompletionProvider end

active_module(repl::LineEditREPL) = repl.mistate === nothing ? Main : repl.mistate.active_module
function active_module() # this method is also called from Base
isdefined(Base, :active_repl) || return Main
return active_module(Base.active_repl::AbstractREPL)
end
active_module((; mistate)::LineEditREPL) = mistate === nothing ? Main : mistate.active_module
active_module(::AbstractREPL) = Main
active_module(d::REPLDisplay) = active_module(d.repl)

setmodifiers!(c::REPLCompletionProvider, m::LineEdit.Modifiers) = c.modifiers = m

"""
activate(mod::Module=Main)
Set `mod` as the default contextual module in the REPL,
both for evaluating expressions and printing them.
"""
function activate(mod::Module=Main)
Base.active_repl.mistate.active_module = mod
mistate = (Base.active_repl::LineEditREPL).mistate
mistate === nothing && return nothing
mistate.active_module = mod
Base.load_InteractiveUtils(mod)
nothing
return nothing
end

beforecursor(buf::IOBuffer) = String(buf.data[1:buf.ptr-1])
Expand Down

0 comments on commit 2c5ebe6

Please sign in to comment.