Skip to content

Commit

Permalink
Add invalidation barriers for displaysize and implicit_typeinfo (#…
Browse files Browse the repository at this point in the history
…56159)

These are invalidated by our own stdlibs (Dates and REPL) unfortunately
so we need to put this barrier in.

This fix is _very_ un-satisfying, because it doesn't do anything to
solve this problem for downstream libraries that use e.g. `displaysize`.
To fix that, I think we need a way to make sure callers get these
invalidation barriers by default...
  • Loading branch information
topolarity authored Oct 15, 2024
1 parent fe82988 commit 9223088
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 10 deletions.
16 changes: 11 additions & 5 deletions base/arrayshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,12 @@ typeinfo_eltype(typeinfo::Type{<:AbstractArray{T}}) where {T} = eltype(typeinfo)
typeinfo_eltype(typeinfo::Type{<:AbstractDict{K,V}}) where {K,V} = eltype(typeinfo)
typeinfo_eltype(typeinfo::Type{<:AbstractSet{T}}) where {T} = eltype(typeinfo)

# This is a fancy way to make de-specialize a call to `typeinfo_implicit(T)`
# which is unfortunately invalidated by Dates
# (https://github.com/JuliaLang/julia/issues/56080)
#
# This makes the call less efficient, but avoids being invalidated by Dates.
_typeinfo_implicit(@nospecialize(T)) = Base.invoke_in_world(Base.tls_world_age(), typeinfo_implicit, T)::Bool

# types that can be parsed back accurately from their un-decorated representations
function typeinfo_implicit(@nospecialize(T))
Expand All @@ -553,9 +559,9 @@ function typeinfo_implicit(@nospecialize(T))
return true
end
return isconcretetype(T) &&
((T <: Array && typeinfo_implicit(eltype(T))) ||
((T <: Tuple || T <: NamedTuple || T <: Pair) && all(typeinfo_implicit, fieldtypes(T))) ||
(T <: AbstractDict && typeinfo_implicit(keytype(T)) && typeinfo_implicit(valtype(T))))
((T <: Array && _typeinfo_implicit(eltype(T))) ||
((T <: Tuple || T <: NamedTuple || T <: Pair) && all(_typeinfo_implicit, fieldtypes(T))) ||
(T <: AbstractDict && _typeinfo_implicit(keytype(T)) && _typeinfo_implicit(valtype(T))))
end

# X not constrained, can be any iterable (cf. show_vector)
Expand All @@ -573,7 +579,7 @@ function typeinfo_prefix(io::IO, X)
if X isa AbstractDict
if eltype_X == eltype_ctx
sprint(show_type_name, typeof(X).name; context=io), false
elseif !isempty(X) && typeinfo_implicit(keytype(X)) && typeinfo_implicit(valtype(X))
elseif !isempty(X) && _typeinfo_implicit(keytype(X)) && _typeinfo_implicit(valtype(X))
sprint(show_type_name, typeof(X).name; context=io), true
else
sprint(print, typeof(X); context=io), false
Expand All @@ -582,7 +588,7 @@ function typeinfo_prefix(io::IO, X)
# Types hard-coded here are those which are created by default for a given syntax
if eltype_X == eltype_ctx
"", false
elseif !isempty(X) && typeinfo_implicit(eltype_X)
elseif !isempty(X) && _typeinfo_implicit(eltype_X)
"", true
elseif print_without_params(eltype_X)
sprint(show_type_name, unwrap_unionall(eltype_X).name; context=io), false # Print "Array" rather than "Array{T,N}"
Expand Down
2 changes: 1 addition & 1 deletion base/logging/ConsoleLogger.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module
if !(isopen(stream)::Bool)
stream = stderr
end
dsize = displaysize(stream)::Tuple{Int,Int}
dsize = Base.displaysize_(stream)::Tuple{Int,Int}
nkwargs = length(kwargs)::Int
if nkwargs > hasmaxlog
valbuf = IOBuffer()
Expand Down
4 changes: 2 additions & 2 deletions base/precompilation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ function precompilepkgs(pkgs::Vector{String}=String[];
n_print_rows = 0
while !printloop_should_exit
lock(print_lock) do
term_size = Base.displaysize(io)::Tuple{Int,Int}
term_size = Base.displaysize_(io)
num_deps_show = max(term_size[1] - 3, 2) # show at least 2 deps
pkg_queue_show = if !interrupted_or_done.set && length(pkg_queue) > num_deps_show
last(pkg_queue, num_deps_show)
Expand All @@ -687,7 +687,7 @@ function precompilepkgs(pkgs::Vector{String}=String[];
bar.max = n_total - n_already_precomp
# when sizing to the terminal width subtract a little to give some tolerance to resizing the
# window between print cycles
termwidth = displaysize(io)[2] - 4
termwidth = Base.displaysize_(io)[2] - 4
if !final_loop
str = sprint(io -> show_progress(io, bar; termwidth, carriagereturn=false); context=io)
print(iostr, Base._truncate_at_width_or_chars(true, str, termwidth), "\n")
Expand Down
4 changes: 2 additions & 2 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ get(io::IO, key, default) = default
keys(io::IOContext) = keys(io.dict)
keys(io::IO) = keys(ImmutableDict{Symbol,Any}())

displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize]::Tuple{Int,Int} : displaysize(io.io)
displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize]::Tuple{Int,Int} : Base.displaysize_(io.io)

show_circular(io::IO, @nospecialize(x)) = false
function show_circular(io::IOContext, @nospecialize(x))
Expand Down Expand Up @@ -2622,7 +2622,7 @@ end
function type_limited_string_from_context(out::IO, str::String)
typelimitflag = get(out, :stacktrace_types_limited, nothing)
if typelimitflag isa RefValue{Bool}
sz = get(out, :displaysize, displaysize(out))::Tuple{Int, Int}
sz = get(out, :displaysize, Base.displaysize_(out))::Tuple{Int, Int}
str_lim = type_depth_limit(str, max(sz[2], 120))
if sizeof(str_lim) < sizeof(str)
typelimitflag[] = true
Expand Down
7 changes: 7 additions & 0 deletions base/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,13 @@ displaysize(io::IO) = displaysize()
displaysize() = (parse(Int, get(ENV, "LINES", "24")),
parse(Int, get(ENV, "COLUMNS", "80")))::Tuple{Int, Int}

# This is a fancy way to make de-specialize a call to `displaysize(io::IO)`
# which is unfortunately invalidated by REPL
# (https://github.com/JuliaLang/julia/issues/56080)
#
# This makes the call less efficient, but avoids being invalidated by REPL.
displaysize_(io::IO) = Base.invoke_in_world(Base.tls_world_age(), displaysize, io)::Tuple{Int,Int}

function displaysize(io::TTY)
check_open(io)

Expand Down

0 comments on commit 9223088

Please sign in to comment.