From 364bfcc89ac064cd7be2dc0b211986cac248a3c7 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 6 Mar 2022 10:03:30 -0600 Subject: [PATCH 01/14] Standardize on String for IO, BinaryPlatform methods This reduces invalidations when loading packages that define new AbstractString types. There doesn't appear to be any particular need for these methods to be re-specialized for anything besides String. --- base/binaryplatforms.jl | 4 +++- base/io.jl | 10 +++++----- base/iostream.jl | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 87c7f029f0563..e2dda00bf58e7 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -667,7 +667,7 @@ const libstdcxx_version_mapping = Dict{String,String}( Parses a string platform triplet back into a `Platform` object. """ -function Base.parse(::Type{Platform}, triplet::AbstractString; validate_strict::Bool = false) +function Base.parse(::Type{Platform}, triplet::String; validate_strict::Bool = false) # Helper function to collapse dictionary of mappings down into a regex of # named capture groups joined by "|" operators c(mapping) = string("(",join(["(?<$k>$v)" for (k, v) in mapping], "|"), ")") @@ -751,6 +751,8 @@ function Base.parse(::Type{Platform}, triplet::AbstractString; validate_strict:: end throw(ArgumentError("Platform `$(triplet)` is not an officially supported platform")) end +Base.parse(::Type{Platform}, triplet::AbstractString; kwargs...) = + parse(Platform, convert(String, triplet)::String; kwargs...) function Base.tryparse(::Type{Platform}, triplet::AbstractString) try diff --git a/base/io.jl b/base/io.jl index 69972249be02f..3fac2287bdabf 100644 --- a/base/io.jl +++ b/base/io.jl @@ -445,7 +445,7 @@ wait_close(io::AbstractPipe) = (wait_close(pipe_writer(io)::IO); wait_close(pipe # Exception-safe wrappers (io = open(); try f(io) finally close(io)) -write(filename::AbstractString, a1, args...) = open(io->write(io, a1, args...), filename, "w") +write(filename::AbstractString, a1, args...) = open(io->write(io, a1, args...), convert(String, filename)::String, "w") """ read(filename::AbstractString, args...) @@ -457,9 +457,9 @@ Open a file and read its contents. `args` is passed to `read`: this is equivalen Read the entire contents of a file as a string. """ -read(filename::AbstractString, args...) = open(io->read(io, args...), filename) +read(filename::AbstractString, args...) = open(io->read(io, args...), convert(String, filename)::String) -read(filename::AbstractString, ::Type{T}) where {T} = open(io->read(io, T), filename) +read(filename::AbstractString, ::Type{T}) where {T} = open(io->read(io, T), convert(String, filename)::String) """ read!(stream::IO, array::AbstractArray) @@ -469,7 +469,7 @@ Read binary data from an I/O stream or file, filling in `array`. """ function read! end -read!(filename::AbstractString, a) = open(io->read!(io, a), filename) +read!(filename::AbstractString, a) = open(io->read!(io, a), convert(String, filename)::String) """ readuntil(stream::IO, delim; keep::Bool = false) @@ -496,7 +496,7 @@ julia> readuntil("my_file.txt", '.', keep = true) julia> rm("my_file.txt") ``` """ -readuntil(filename::AbstractString, args...; kw...) = open(io->readuntil(io, args...; kw...), filename) +readuntil(filename::AbstractString, args...; kw...) = open(io->readuntil(io, args...; kw...), convert(String, filename)::String) """ readline(io::IO=stdin; keep::Bool=false) diff --git a/base/iostream.jl b/base/iostream.jl index 0af0e244cf357..23dfb53256e82 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -272,7 +272,7 @@ safe multi-threaded access. !!! compat "Julia 1.5" The `lock` argument is available as of Julia 1.5. """ -function open(fname::AbstractString; lock = true, +function open(fname::String; lock = true, read :: Union{Bool,Nothing} = nothing, write :: Union{Bool,Nothing} = nothing, create :: Union{Bool,Nothing} = nothing, @@ -299,6 +299,7 @@ function open(fname::AbstractString; lock = true, end return s end +open(fname::AbstractString; kwargs...) = open(convert(String, fname)::String; kwargs...) """ open(filename::AbstractString, [mode::AbstractString]; lock = true) -> IOStream From e76547794750f34ce2d57213ba14370696669e17 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 6 Mar 2022 10:04:20 -0600 Subject: [PATCH 02/14] Improve IO inference in process spawning --- base/process.jl | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/base/process.jl b/base/process.jl index 6aac514191681..096e155f29fea 100644 --- a/base/process.jl +++ b/base/process.jl @@ -69,7 +69,8 @@ function _uv_hook_close(proc::Process) nothing end -const SpawnIOs = Vector{Any} # convenience name for readability +const SpawnIO = Redirectable +const SpawnIOs = Vector{SpawnIO} # convenience name for readability function as_cpumask(cpus::Vector{UInt16}) n = max(Int(maximum(cpus)), Int(ccall(:uv_cpumask_size, Cint, ()))) @@ -119,7 +120,7 @@ end return pp end -_spawn(cmds::AbstractCmd) = _spawn(cmds, Any[]) +_spawn(cmds::AbstractCmd) = _spawn(cmds, SpawnIO[]) # optimization: we can spawn `Cmd` directly without allocating the ProcessChain function _spawn(cmd::Cmd, stdios::SpawnIOs) @@ -203,7 +204,7 @@ end # open the child end of each element of `stdios`, and initialize the parent end function setup_stdios(f, stdios::SpawnIOs) nstdio = length(stdios) - open_io = Vector{Any}(undef, nstdio) + open_io = SpawnIOs(undef, nstdio) close_io = falses(nstdio) try for i in 1:nstdio @@ -314,19 +315,19 @@ close_stdio(stdio) = close(stdio) # - An Filesystem.File or IOStream object to redirect the output to # - A FileRedirect, containing a string specifying a filename to be opened for the child -spawn_opts_swallow(stdios::StdIOSet) = Any[stdios...] -spawn_opts_inherit(stdios::StdIOSet) = Any[stdios...] +spawn_opts_swallow(stdios::StdIOSet) = SpawnIO[stdios...] +spawn_opts_inherit(stdios::StdIOSet) = SpawnIO[stdios...] spawn_opts_swallow(in::Redirectable=devnull, out::Redirectable=devnull, err::Redirectable=devnull) = - Any[in, out, err] + SpawnIO[in, out, err] # pass original descriptors to child processes by default, because we might # have already exhausted and closed the libuv object for our standard streams. # ref issue #8529 spawn_opts_inherit(in::Redirectable=RawFD(0), out::Redirectable=RawFD(1), err::Redirectable=RawFD(2)) = - Any[in, out, err] + SpawnIO[in, out, err] function eachline(cmd::AbstractCmd; keep::Bool=false) out = PipeEndpoint() - processes = _spawn(cmd, Any[devnull, out, stderr]) + processes = _spawn(cmd, SpawnIO[devnull, out, stderr]) # if the user consumes all the data, also check process exit status for success ondone = () -> (success(processes) || pipeline_error(processes); nothing) return EachLine(out, keep=keep, ondone=ondone)::EachLine @@ -374,20 +375,20 @@ function open(cmds::AbstractCmd, stdio::Redirectable=devnull; write::Bool=false, stdio === devnull || throw(ArgumentError("no stream can be specified for `stdio` in read-write mode")) in = PipeEndpoint() out = PipeEndpoint() - processes = _spawn(cmds, Any[in, out, stderr]) + processes = _spawn(cmds, SpawnIO[in, out, stderr]) processes.in = in processes.out = out elseif read out = PipeEndpoint() - processes = _spawn(cmds, Any[stdio, out, stderr]) + processes = _spawn(cmds, SpawnIO[stdio, out, stderr]) processes.out = out elseif write in = PipeEndpoint() - processes = _spawn(cmds, Any[in, stdio, stderr]) + processes = _spawn(cmds, SpawnIO[in, stdio, stderr]) processes.in = in else stdio === devnull || throw(ArgumentError("no stream can be specified for `stdio` in no-access mode")) - processes = _spawn(cmds, Any[devnull, devnull, stderr]) + processes = _spawn(cmds, SpawnIO[devnull, devnull, stderr]) end return processes end From 60d55647641cd61f03d0b078e9dcb158d965e018 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 6 Mar 2022 10:05:31 -0600 Subject: [PATCH 03/14] Improve vararg string This is follow-on work to #43939 --- base/strings/substring.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 5142cf65fe9c5..2c701a03d0633 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -229,7 +229,13 @@ function string(a::Union{Char, String, SubString{String}, Symbol}...) out = _string_n(n) offs = 1 for v in a - offs += __unsafe_string!(out, v, offs) + if v isa Char + offs += __unsafe_string!(out, v, offs) + elseif v isa String || v isa SubString{String} + offs += __unsafe_string!(out, v, offs) + else + offs += __unsafe_string!(out, v::Symbol, offs) + end end return out end From 7d122b990ef1b1f55f3596899d08e8919cb0e1dc Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 6 Mar 2022 10:05:56 -0600 Subject: [PATCH 04/14] Improve inference at a few callsites --- base/logging.jl | 2 +- base/show.jl | 5 +++-- stdlib/REPL/src/LineEdit.jl | 2 +- stdlib/REPL/src/TerminalMenus/AbstractMenu.jl | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/base/logging.jl b/base/logging.jl index 667b8ddead983..20c152e90697c 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -457,7 +457,7 @@ end msg = try "Exception while generating log record in module $_module at $filepath:$line" catch ex - "Exception handling log message: $ex" + "Exception handling log message: $(ex::Exception)" end bt = real ? catch_backtrace() : backtrace() handle_message( diff --git a/base/show.jl b/base/show.jl index 8359690034c23..c5701cf5fd6e2 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1919,7 +1919,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In na = length(func_args) if (na == 2 || (na > 2 && isa(func, Symbol) && func in (:+, :++, :*)) || (na == 3 && func === :(:))) && all(a -> !isa(a, Expr) || a.head !== :..., func_args) - sep = func === :(:) ? "$func" : " $func " + sep = func === :(:) ? "$func" : " " * repr(func) * " " # if func::Any, avoid string interpolation (invalidation) if func_prec <= prec show_enclosed_list(io, '(', func_args, sep, ')', indent, func_prec, quote_level, true) @@ -2289,7 +2289,8 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In elseif head === :meta && nargs == 1 && args[1] === :pop_loc print(io, "# meta: pop location") elseif head === :meta && nargs == 2 && args[1] === :pop_loc - print(io, "# meta: pop locations ($(args[2]))") + loc = args[2]::Int + print(io, "# meta: pop locations ($loc)") # print anything else as "Expr(head, args...)" else unhandled = true diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index cf09cb1966bf1..89f57383d5e48 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -1646,7 +1646,7 @@ end throw_eager_redirection_cycle(key::Union{Char, String}) = error("Eager redirection cycle detected for key ", repr(key)) throw_could_not_find_redirected_value(key::Union{Char, String}) = - error("Could not find redirected value ", repl(key)) + error("Could not find redirected value ", repr(key)) function keymap_unify(keymaps) ret = Dict{Char,Any}() diff --git a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl index b87a9c8c26464..441aff176ffdf 100644 --- a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl +++ b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl @@ -192,7 +192,7 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio REPL.Terminals.raw!(term, true) true catch err - suppress_output || @warn("TerminalMenus: Unable to enter raw mode: $err") + suppress_output || @warn("TerminalMenus: Unable to enter raw mode: $(err::Exception)") false end # hide the cursor From 801da30403b7a7a50720fd2886cfabd5575a5e41 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 7 Mar 2022 03:33:45 -0600 Subject: [PATCH 05/14] Improve typing of EnvDict in p7zip --- stdlib/p7zip_jll/src/p7zip_jll.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/p7zip_jll/src/p7zip_jll.jl b/stdlib/p7zip_jll/src/p7zip_jll.jl index 99b346017ad97..4320003b282f7 100644 --- a/stdlib/p7zip_jll/src/p7zip_jll.jl +++ b/stdlib/p7zip_jll/src/p7zip_jll.jl @@ -35,7 +35,7 @@ else const pathsep = ':' end -function adjust_ENV!(env::Dict, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool) +function adjust_ENV!(env::Dict{keytype(Base.EnvDict),valtype(Base.EnvDict)}, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool) if adjust_LIBPATH LIBPATH_base = get(env, LIBPATH_env, expanduser(LIBPATH_default)) if !isempty(LIBPATH_base) From ddc2dba133e991a5f1f4c0eaab286fecec63dfc7 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 8 Mar 2022 04:19:09 -0600 Subject: [PATCH 06/14] Don't break show --- base/show.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index c5701cf5fd6e2..8596e1b2e58da 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1919,7 +1919,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In na = length(func_args) if (na == 2 || (na > 2 && isa(func, Symbol) && func in (:+, :++, :*)) || (na == 3 && func === :(:))) && all(a -> !isa(a, Expr) || a.head !== :..., func_args) - sep = func === :(:) ? "$func" : " " * repr(func) * " " # if func::Any, avoid string interpolation (invalidation) + sep = func === :(:) ? "$func" : " " * string(func) * " " # if func::Any, avoid string interpolation (invalidation) if func_prec <= prec show_enclosed_list(io, '(', func_args, sep, ')', indent, func_prec, quote_level, true) From 41562442def5eb55fcc64d2803b3ef31f228645b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 8 Mar 2022 09:40:14 -0600 Subject: [PATCH 07/14] Switch logging to LazyString --- base/logging.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/logging.jl b/base/logging.jl index 20c152e90697c..a2d2f903c110a 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -457,7 +457,7 @@ end msg = try "Exception while generating log record in module $_module at $filepath:$line" catch ex - "Exception handling log message: $(ex::Exception)" + LazyString("Exception handling log message: ", ex) end bt = real ? catch_backtrace() : backtrace() handle_message( From 78bcd25ced028757da21b497a76aca72db418f97 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 8 Mar 2022 09:40:47 -0600 Subject: [PATCH 08/14] Simplify SpawnIO type --- base/process.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/process.jl b/base/process.jl index 096e155f29fea..955713da523c4 100644 --- a/base/process.jl +++ b/base/process.jl @@ -69,7 +69,7 @@ function _uv_hook_close(proc::Process) nothing end -const SpawnIO = Redirectable +const SpawnIO = Union{IO, RawFD} const SpawnIOs = Vector{SpawnIO} # convenience name for readability function as_cpumask(cpus::Vector{UInt16}) From 5fe26ff1bb7fb1990b4a5bc0329a42f2e72b7bcf Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 8 Mar 2022 09:41:06 -0600 Subject: [PATCH 09/14] Better fix for show --- base/show.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index 8596e1b2e58da..376461378867d 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1919,7 +1919,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In na = length(func_args) if (na == 2 || (na > 2 && isa(func, Symbol) && func in (:+, :++, :*)) || (na == 3 && func === :(:))) && all(a -> !isa(a, Expr) || a.head !== :..., func_args) - sep = func === :(:) ? "$func" : " " * string(func) * " " # if func::Any, avoid string interpolation (invalidation) + sep = func === :(:) ? "$func" : " " * convert(String, string(func))::String * " " # if func::Any, avoid string interpolation (invalidation) if func_prec <= prec show_enclosed_list(io, '(', func_args, sep, ')', indent, func_prec, quote_level, true) From 0012411703c8788ef5cd75ec3125b47e30ec5329 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 8 Mar 2022 09:42:15 -0600 Subject: [PATCH 10/14] Prepare for invalidation-resistant calls to `match` --- base/strings/substring.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 2c701a03d0633..86efbc1f6df3e 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -55,6 +55,11 @@ convert(::Type{SubString{S}}, s::AbstractString) where {S<:AbstractString} = SubString(convert(S, s)) convert(::Type{T}, s::T) where {T<:SubString} = s +# Regex match allows only Union{String, SubString{String}} so define conversion to this type +convert(::Type{Union{String, SubString{String}}}, s::String) = s +convert(::Type{Union{String, SubString{String}}}, s::SubString{String}) = s +convert(::Type{Union{String, SubString{String}}}, s::AbstractString) = convert(String, s) + function String(s::SubString{String}) parent = s.string copy = GC.@preserve parent unsafe_string(pointer(parent, s.offset+1), s.ncodeunits) From d1b61ea15d40cf27aa2e96e2e9a5d4eb7ad9e4d4 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 9 Mar 2022 06:00:16 -0600 Subject: [PATCH 11/14] Fix Windows --- base/process.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/process.jl b/base/process.jl index 955713da523c4..4ee95369d0963 100644 --- a/base/process.jl +++ b/base/process.jl @@ -69,7 +69,7 @@ function _uv_hook_close(proc::Process) nothing end -const SpawnIO = Union{IO, RawFD} +const SpawnIO = Union{IO, RawFD, OS_HANDLE} const SpawnIOs = Vector{SpawnIO} # convenience name for readability function as_cpumask(cpus::Vector{UInt16}) From bff9c2ff4dceabf5790dbd95722b0a7dd03a86af Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 11 Mar 2022 05:49:33 -0600 Subject: [PATCH 12/14] more fix --- base/logging.jl | 2 +- base/show.jl | 3 +-- stdlib/Logging/src/ConsoleLogger.jl | 2 +- stdlib/REPL/src/TerminalMenus/AbstractMenu.jl | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/base/logging.jl b/base/logging.jl index a2d2f903c110a..f4595d7616d59 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -674,7 +674,7 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module, end iob = IOContext(buf, stream) levelstr = level == Warn ? "Warning" : string(level) - msglines = eachsplit(chomp(string(message)::String), '\n') + msglines = eachsplit(chomp(convert(String, message)::String), '\n') msg1, rest = Iterators.peel(msglines) println(iob, "┌ ", levelstr, ": ", msg1) for msg in rest diff --git a/base/show.jl b/base/show.jl index 376461378867d..999a73047f6b2 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2289,8 +2289,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In elseif head === :meta && nargs == 1 && args[1] === :pop_loc print(io, "# meta: pop location") elseif head === :meta && nargs == 2 && args[1] === :pop_loc - loc = args[2]::Int - print(io, "# meta: pop locations ($loc)") + print(io, "# meta: pop locations ($(args[2]::Int))") # print anything else as "Expr(head, args...)" else unhandled = true diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 4e32b6b71f656..25c6de7c7fdc6 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -116,7 +116,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Generate a text representation of the message and all key value pairs, # split into lines. - msglines = [(indent=0, msg=l) for l in split(chomp(string(message)::String), '\n')] + msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, message)::String), '\n')] stream = logger.stream if !isopen(stream) stream = stderr diff --git a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl index 441aff176ffdf..c98dad11441c4 100644 --- a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl +++ b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl @@ -192,7 +192,7 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio REPL.Terminals.raw!(term, true) true catch err - suppress_output || @warn("TerminalMenus: Unable to enter raw mode: $(err::Exception)") + suppress_output || @warn(LazyString("TerminalMenus: Unable to enter raw mode: ", err)) false end # hide the cursor From 4fec731eb03ceee0cee78cf51c377fdae73d18ea Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 12 Mar 2022 05:22:53 -0600 Subject: [PATCH 13/14] Fix logging code --- base/logging.jl | 2 +- stdlib/Logging/src/ConsoleLogger.jl | 2 +- test/corelogging.jl | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/base/logging.jl b/base/logging.jl index f4595d7616d59..1b8e5e0f54192 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -674,7 +674,7 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module, end iob = IOContext(buf, stream) levelstr = level == Warn ? "Warning" : string(level) - msglines = eachsplit(chomp(convert(String, message)::String), '\n') + msglines = eachsplit(chomp(convert(String, string(message))::String), '\n') msg1, rest = Iterators.peel(msglines) println(iob, "┌ ", levelstr, ": ", msg1) for msg in rest diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 25c6de7c7fdc6..86e3d587eb452 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -116,7 +116,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Generate a text representation of the message and all key value pairs, # split into lines. - msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, message)::String), '\n')] + msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, string(message))::String), '\n')] stream = logger.stream if !isopen(stream) stream = stderr diff --git a/test/corelogging.jl b/test/corelogging.jl index 9c5102d848013..3fce2dd593595 100644 --- a/test/corelogging.jl +++ b/test/corelogging.jl @@ -151,6 +151,21 @@ end @test_throws MethodError @macrocall(@error) end +@testset "Any type" begin + @test_logs (:info, sum) @info sum + # TODO: make this work (here we want `@test_logs` to fail) + # @test_fails @test_logs (:info, "sum") @info sum # `sum` works, `"sum"` does not + + # check that the message delivered to the user works + mktempdir() do dir + path_stdout = joinpath(dir, "stdout.txt") + path_stderr = joinpath(dir, "stderr.txt") + redirect_stdio(stdout=path_stdout, stderr=path_stderr) do + @info sum + end + @test occursin("Info: sum", read(path_stderr, String)) + end +end #------------------------------------------------------------------------------- # Early log level filtering From 54e486c133485869e0a489ff89b5b7331f5ff94b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 12 Mar 2022 05:29:03 -0600 Subject: [PATCH 14/14] pass exception via key --- stdlib/REPL/src/TerminalMenus/AbstractMenu.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl index c98dad11441c4..127d0cd88a2cf 100644 --- a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl +++ b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl @@ -192,7 +192,7 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio REPL.Terminals.raw!(term, true) true catch err - suppress_output || @warn(LazyString("TerminalMenus: Unable to enter raw mode: ", err)) + suppress_output || @warn "TerminalMenus: Unable to enter raw mode: " exception=(err, catch_backtrace()) false end # hide the cursor