From 7f6dac08697b61670233eb50081ee4d95353d8ac Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 15 May 2020 07:33:56 -0500 Subject: [PATCH 1/8] Prevent more ! invalidations from IOContexts All of these "fields" are documented to be Bool, so this should not break any code and may improve error messages in case of user error. Usages like `if limit...`, `limit ? a : b`, or `limit && return nothing` do not need these fixes, since these are baked into the language rather than being handled by dispatch. --- base/Enums.jl | 2 +- base/arrayshow.jl | 2 +- base/channels.jl | 2 +- base/dict.jl | 2 +- base/range.jl | 1 - base/ryu/Ryu.jl | 2 +- base/show.jl | 14 +++++++------- stdlib/REPL/src/REPL.jl | 2 +- stdlib/SparseArrays/src/sparsematrix.jl | 2 +- stdlib/SparseArrays/src/sparsevector.jl | 2 +- 10 files changed, 15 insertions(+), 16 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index b4c02327dd5e2..41e9da63920ac 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -29,7 +29,7 @@ Base.print(io::IO, x::Enum) = print(io, Symbol(x)) function Base.show(io::IO, x::Enum) sym = Symbol(x) - if !get(io, :compact, false) + if !(get(io, :compact, false)::Bool) from = get(io, :module, Main) def = typeof(x).name.module if from === nothing || !Base.isvisible(sym, def, from) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index 338f511950d51..d57320dfdfb24 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -166,7 +166,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, vdots::AbstractString = "\u22ee", ddots::AbstractString = " \u22f1 ", hmod::Integer = 5, vmod::Integer = 5) - if !get(io, :limit, false) + if !(get(io, :limit, false)::Bool) screenheight = screenwidth = typemax(Int) else sz = displaysize(io) diff --git a/base/channels.jl b/base/channels.jl index 40f151e54f456..36c2f041a06e4 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -444,7 +444,7 @@ show(io::IO, c::Channel) = print(io, typeof(c), "(", c.sz_max, ")") function show(io::IO, ::MIME"text/plain", c::Channel) show(io, c) - if !get(io, :compact, false) + if !(get(io, :compact, false)::Bool) if !isopen(c) print(io, " (closed)") else diff --git a/base/dict.jl b/base/dict.jl index 109538e70cf4f..65eacd9b1962b 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -25,7 +25,7 @@ function show(io::IO, t::AbstractDict{K,V}) where V where K recur_io = IOContext(io, :SHOWN_SET => t, :typeinfo => eltype(t)) - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool # show in a Julia-syntax-like form: Dict(k=>v, ...) print(io, typeinfo_prefix(io, t)[1]) print(io, '(') diff --git a/base/range.jl b/base/range.jl index 350c70ce3bead..243acb40660b9 100644 --- a/base/range.jl +++ b/base/range.jl @@ -457,7 +457,6 @@ function print_range(io::IO, r::AbstractRange, hdots::AbstractString = ",\u2026,") # horiz ellipsis # This function borrows from print_matrix() in show.jl # and should be called by show and display - limit = get(io, :limit, false) sz = displaysize(io) if !haskey(io, :compact) io = IOContext(io, :compact => true) diff --git a/base/ryu/Ryu.jl b/base/ryu/Ryu.jl index 62600236b20da..1d260fe9b3696 100644 --- a/base/ryu/Ryu.jl +++ b/base/ryu/Ryu.jl @@ -109,7 +109,7 @@ function writeexp(x::T, end function Base.show(io::IO, x::T, forceuntyped::Bool=false, fromprint::Bool=false) where {T <: Base.IEEEFloat} - compact = get(io, :compact, false) + compact = get(io, :compact, false)::Bool buf = Base.StringVector(neededdigits(T)) typed = !forceuntyped && !compact && get(io, :typeinfo, Any) != typeof(x) pos = writeshortest(buf, 1, x, false, false, true, -1, diff --git a/base/show.jl b/base/show.jl index 987a146d9ee5e..1ccdfd2138163 100644 --- a/base/show.jl +++ b/base/show.jl @@ -49,7 +49,7 @@ function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator}) summary(io, iter) isempty(iter) && return print(io, ". ", isa(iter,KeySet) ? "Keys" : "Values", ":") - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool if limit sz = displaysize(io) rows, cols = sz[1] - 3, sz[2] @@ -79,7 +79,7 @@ function show(io::IO, ::MIME"text/plain", t::AbstractDict{K,V}) where {K,V} isempty(t) && return show(io, t) # show more descriptively, with one line per key/value pair recur_io = IOContext(io, :SHOWN_SET => t) - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool if !haskey(io, :compact) recur_io = IOContext(recur_io, :compact => true) end @@ -149,7 +149,7 @@ function show(io::IO, ::MIME"text/plain", t::AbstractSet{T}) where T isempty(t) && return show(io, t) # show more descriptively, with one line per value recur_io = IOContext(io, :SHOWN_SET => t) - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool summary(io, t) isempty(t) && return @@ -450,11 +450,11 @@ function show_function(io::IO, f::Function, compact::Bool) end end -show(io::IO, f::Function) = show_function(io, f, get(io, :compact, false)) +show(io::IO, f::Function) = show_function(io, f, get(io, :compact, false)::Bool) print(io::IO, f::Function) = show_function(io, f, true) function show(io::IO, f::Core.IntrinsicFunction) - if !get(io, :compact, false) + if !(get(io, :compact, false)::Bool) print(io, "Core.Intrinsics.") end print(io, nameof(f)) @@ -564,7 +564,7 @@ function show_type_name(io::IO, tn::Core.TypeName) sym = (globfunc ? globname : tn.name)::Symbol globfunc && print(io, "typeof(") quo = false - if !get(io, :compact, false) + if !(get(io, :compact, false)::Bool) # Print module prefix unless type is visible from module passed to # IOContext If :module is not set, default to Main. nothing can be used # to force printing prefix @@ -2129,7 +2129,7 @@ function alignment(io::IO, x::Pair) ctx = IOContext(io, :typeinfo => gettypeinfos(io, x)[1]) left = length(sprint(show, x.first, context=ctx, sizehint=0)) left += 2 * !isdelimited(ctx, x.first) # for parens around p.first - left += !get(io, :compact, false) # spaces are added around "=>" + left += !(get(io, :compact, false)::Bool) # spaces are added around "=>" (left+1, length(s)-left-1) # +1 for the "=" part of "=>" else (0, length(s)) # as for x::Any diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 30af00a6cdc06..5259a4fd717e8 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1161,7 +1161,7 @@ StreamREPL(stream::IO) = StreamREPL(stream, Base.text_colors[:green], Base.input run_repl(stream::IO) = run_repl(StreamREPL(stream)) outstream(s::StreamREPL) = s.stream -hascolor(s::StreamREPL) = get(s.stream, :color, false) +hascolor(s::StreamREPL) = get(s.stream, :color, false)::Bool answer_color(r::LineEditREPL) = r.envcolors ? Base.answer_color() : r.answer_color answer_color(r::StreamREPL) = r.answer_color diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index ba8d2fba823a5..4b64362f6d3e4 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -275,7 +275,7 @@ function _show_with_braille_patterns(io::IOContext, S::AbstractSparseMatrixCSC) end function Base.show(io::IOContext, S::AbstractSparseMatrixCSC) - if max(size(S)...) < 16 && !get(io, :compact, false) + if max(size(S)...) < 16 && !(get(io, :compact, false)::Bool) ioc = IOContext(io, :compact => true) println(ioc) Base.print_matrix(ioc, S) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index e4add06a2ef98..2cc9268e6fea8 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -854,7 +854,7 @@ function show(io::IOContext, x::AbstractSparseVector) if isempty(nzind) return show(io, MIME("text/plain"), x) end - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool half_screen_rows = limit ? div(displaysize(io)[1] - 8, 2) : typemax(Int) pad = ndigits(n) if !haskey(io, :compact) From 7237fca7c0fdbdac218286881933aecc1a84fd96 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 18 May 2020 08:08:26 -0500 Subject: [PATCH 2/8] Add some typeasserts to reduce invalidation --- base/Enums.jl | 1 + base/show.jl | 2 +- base/strings/basic.jl | 2 +- stdlib/LibGit2/src/gitcredential.jl | 6 +++--- stdlib/REPL/src/docview.jl | 6 +++--- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 41e9da63920ac..fe15ea2110781 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -159,6 +159,7 @@ macro enum(T, syms...) else throw(ArgumentError(string("invalid argument for Enum ", typename, ": ", s))) end + s = s::Symbol if !Base.isidentifier(s) throw(ArgumentError("invalid name for Enum $typename; \"$s\" is not a valid identifier")) end diff --git a/base/show.jl b/base/show.jl index 1ccdfd2138163..e0e5e8bef75f6 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1198,7 +1198,7 @@ function show_import_path(io::IO, ex, quote_level) if i > 1 && ex.args[i-1] !== :(.) print(io, '.') end - show_sym(io, ex.args[i], allow_macroname=(i==length(ex.args))) + show_sym(io, ex.args[i]::Symbol, allow_macroname=(i==length(ex.args))) end else show_unquoted(io, ex, 0, 0, quote_level) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index e36a7fe92504d..9eb301339fa7d 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -290,7 +290,7 @@ julia> cmp("b", "β") function cmp(a::AbstractString, b::AbstractString) a === b && return 0 a, b = Iterators.Stateful(a), Iterators.Stateful(b) - for (c, d) in zip(a, b) + for (c::AbstractChar, d::AbstractChar) in zip(a, b) c ≠ d && return ifelse(c < d, -1, 1) end isempty(a) && return ifelse(isempty(b), 0, -1) diff --git a/stdlib/LibGit2/src/gitcredential.jl b/stdlib/LibGit2/src/gitcredential.jl index 246ce075d24bd..0a442337531a7 100644 --- a/stdlib/LibGit2/src/gitcredential.jl +++ b/stdlib/LibGit2/src/gitcredential.jl @@ -102,11 +102,11 @@ end function Base.read!(io::IO, cred::GitCredential) # https://git-scm.com/docs/git-credential#IOFMT - while !eof(io) - key = readuntil(io, '=') + while !(eof(io)::Bool) + key::AbstractString = readuntil(io, '=') if key == "password" value = Base.SecretBuffer() - while !eof(io) && (c = read(io, UInt8)) != UInt8('\n') + while !(eof(io)::Bool) && (c = read(io, UInt8)) != UInt8('\n') write(value, c) end seekstart(value) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 89451e80023e0..1b85278cccc03 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -607,9 +607,9 @@ moduleusings(mod) = ccall(:jl_module_usings, Any, (Any,), mod) filtervalid(names) = filter(x->!occursin(r"#", x), map(string, names)) accessible(mod::Module) = - [filter!(s -> !Base.isdeprecated(mod, s), names(mod, all = true, imported = true)); - map(names, moduleusings(mod))...; - collect(keys(Base.Docs.keywords))] |> unique |> filtervalid + Symbol[filter!(s -> !Base.isdeprecated(mod, s), names(mod, all=true, imported=true)); + map(names, moduleusings(mod))...; + collect(keys(Base.Docs.keywords))] |> unique |> filtervalid doc_completions(name) = fuzzysort(name, accessible(Main)) doc_completions(name::Symbol) = doc_completions(string(name)) From d54e26f35187d9dcb56f7561ca270b5752ba192a Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 18 May 2020 08:12:06 -0500 Subject: [PATCH 3/8] Add a defensive ambiguity-resolving method --- base/abstractarray.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 918c6c0a88ff8..3a5468842228a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1064,6 +1064,7 @@ _getindex(::IndexStyle, A::AbstractArray, I...) = error("getindex for $(typeof(A)) with types $(typeof(I)) is not supported") ## IndexLinear Scalar indexing: canonical method is one Int +_getindex(::IndexLinear, A::AbstractVector, i::Int) = (@_propagate_inbounds_meta; getindex(A, i)) # ambiguity resolution in case packages specialize this (to be avoided if at all possible, but see Interpolations.jl) _getindex(::IndexLinear, A::AbstractArray, i::Int) = (@_propagate_inbounds_meta; getindex(A, i)) function _getindex(::IndexLinear, A::AbstractArray, I::Vararg{Int,M}) where M @_inline_meta From 35524a906bc2c099f7892c45c6f391110ef58cb5 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 18 May 2020 08:11:45 -0500 Subject: [PATCH 4/8] Add `show` method for `RawFD` This prevents invalidation via `convert(::Type{Ptr{Cint}}, fd)`. --- base/libc.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/libc.jl b/base/libc.jl index 379c76dfd8c60..b8cca87ff6ce0 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -38,6 +38,8 @@ dup(src::RawFD, target::RawFD) = systemerror("dup", -1 == ccall((@static Sys.iswindows() ? :_dup2 : :dup2), Int32, (RawFD, RawFD), src, target)) +show(io::IO, fd::RawFD) = print(io, "RawFD(", bitcast(UInt32, fd), ')') # avoids invalidation via show_default + # Wrapper for an OS file descriptor (for Windows) if Sys.iswindows() primitive type WindowsRawSocket sizeof(Ptr) * 8 end # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows From b5de2553f0d73ebf5558a48549f99bf1c8e602ae Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 18 May 2020 18:08:11 -0500 Subject: [PATCH 5/8] Ensure all `eof` methods return Bool --- base/io.jl | 2 +- stdlib/Base64/src/decode.jl | 2 +- stdlib/REPL/src/Terminals.jl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base/io.jl b/base/io.jl index 811b94abb8673..178df80f30796 100644 --- a/base/io.jl +++ b/base/io.jl @@ -387,7 +387,7 @@ it is always safe to read one byte after seeing `eof` return `false`. `eof` will `false` as long as buffered data is still available, even if the remote end of a connection is closed. """ -eof(io::AbstractPipe) = eof(pipe_reader(io)) +eof(io::AbstractPipe) = eof(pipe_reader(io)::IO)::Bool reseteof(io::AbstractPipe) = reseteof(pipe_reader(io)) diff --git a/stdlib/Base64/src/decode.jl b/stdlib/Base64/src/decode.jl index 1a0a8570fc2de..f997daee286b2 100644 --- a/stdlib/Base64/src/decode.jl +++ b/stdlib/Base64/src/decode.jl @@ -123,7 +123,7 @@ function Base.readbytes!(pipe::Base64DecodePipe, data::AbstractVector{UInt8}, nb return filled end -Base.eof(pipe::Base64DecodePipe) = isempty(pipe.rest) && eof(pipe.io) +Base.eof(pipe::Base64DecodePipe) = isempty(pipe.rest) && eof(pipe.io)::Bool Base.close(pipe::Base64DecodePipe) = nothing # Decode data from (b1, b2, b3, b5, buffer, input) into (ptr, rest). diff --git a/stdlib/REPL/src/Terminals.jl b/stdlib/REPL/src/Terminals.jl index ac00f89b22b4c..5bea8c1a4b96d 100644 --- a/stdlib/REPL/src/Terminals.jl +++ b/stdlib/REPL/src/Terminals.jl @@ -96,8 +96,8 @@ disable_bracketed_paste(t::TextTerminal) = nothing abstract type UnixTerminal <: TextTerminal end -pipe_reader(t::UnixTerminal) = t.in_stream -pipe_writer(t::UnixTerminal) = t.out_stream +pipe_reader(t::UnixTerminal) = t.in_stream::IO +pipe_writer(t::UnixTerminal) = t.out_stream::IO mutable struct TerminalBuffer <: UnixTerminal out_stream::IO From e6813478a902ebabbb43d177d13e93dcd12a5fd1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 23 May 2020 04:57:57 -0500 Subject: [PATCH 6/8] Fix inference of `Docs.meta(::Module)` --- base/docs/Docs.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 0d8665d0e54a4..91866e9db37d1 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -71,12 +71,13 @@ export doc const modules = Module[] const META = gensym(:meta) +const METAType = IdDict{Any,Any} -meta(m::Module) = isdefined(m, META) ? getfield(m, META) : IdDict() +meta(m::Module) = isdefined(m, META) ? getfield(m, META)::METAType : METAType() function initmeta(m::Module) if !isdefined(m, META) - Core.eval(m, :(const $META = $(IdDict()))) + Core.eval(m, :(const $META = $(METAType()))) push!(modules, m) end nothing @@ -204,9 +205,9 @@ mutable struct MultiDoc "Ordered (via definition order) vector of object signatures." order::Vector{Type} "Documentation for each object. Keys are signatures." - docs::IdDict{Any,Any} + docs::METAType - MultiDoc() = new(Type[], IdDict()) + MultiDoc() = new(Type[], METAType()) end # Docstring registration. From c51b0c8428609b46eed6381916092b181a0e803a Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 23 May 2020 08:04:25 -0500 Subject: [PATCH 7/8] Prevent collect dispatch on Expr.args If you know you're building args of any Expr, you might as well start out collecting the arguments to a Vector{Any}, rather than using the clever type-narrowing machinery of collect/map/broadcast. --- base/abstractarray.jl | 2 ++ base/docs/Docs.jl | 13 +++++++------ base/expr.jl | 6 +++--- base/fastmath.jl | 2 +- base/views.jl | 8 ++++---- stdlib/Markdown/src/Julia/interp.jl | 2 +- stdlib/Markdown/src/Markdown.jl | 2 +- stdlib/Markdown/src/parse/config.jl | 2 +- 8 files changed, 20 insertions(+), 17 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 3a5468842228a..703895a96ba26 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2150,6 +2150,8 @@ end # map on collections map(f, A::AbstractArray) = collect_similar(A, Generator(f,A)) +mapany(f, itr) = map!(f, Vector{Any}(undef, length(itr)), itr) # convenient for Expr.args + # default to returning an Array for `map` on general iterators """ map(f, c...) -> collection diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 91866e9db37d1..8ba3949082008 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -62,7 +62,7 @@ include("bindings.jl") import .Base.Meta: quot, isexpr import .Base: Callable, with_output_color -using .Base: RefValue +using .Base: RefValue, mapany import ..CoreDocs: lazy_iterpolate export doc @@ -96,7 +96,7 @@ function signature!(tv, expr::Expr) push!(sig.args[end].args, argtype(arg)) end if isexpr(expr.args[1], :curly) && isempty(tv) - append!(tv, tvar.(expr.args[1].args[2:end])) + append!(tv, mapany(tvar, expr.args[1].args[2:end])) end for i = length(tv):-1:1 push!(sig.args, :(Tuple{$(tv[i].args[1])})) @@ -106,7 +106,7 @@ function signature!(tv, expr::Expr) end return sig elseif isexpr(expr, :where) - append!(tv, tvar.(expr.args[2:end])) + append!(tv, mapany(tvar, expr.args[2:end])) return signature!(tv, expr.args[1]) else return signature!(tv, expr.args[1]) @@ -332,13 +332,14 @@ function metadata(__source__, __module__, expr, ismodule) end if isexpr(expr, :struct) # Field docs for concrete types. - fields = [] + P = Pair{Any,Any} + fields = P[] last_docstr = nothing for each in expr.args[3].args if isa(each, Symbol) || isexpr(each, :(::)) # a field declaration if last_docstr !== nothing - push!(fields, (namify(each), last_docstr)) + push!(fields, P(namify(each), last_docstr)) last_docstr = nothing end elseif isexpr(each, :function) || isexpr(each, :(=)) @@ -349,7 +350,7 @@ function metadata(__source__, __module__, expr, ismodule) last_docstr = each end end - dict = :($(Dict)($([:($(Pair)($(quot(f)), $d)) for (f, d) in fields]...))) + dict = :($(Dict)($([(:($(P)($(quot(f)), $d)))::Expr for (f, d) in fields]...))) push!(args, :($(Pair)(:fields, $dict))) end return :($(Dict)($(args...))) diff --git a/base/expr.jl b/base/expr.jl index 4e7dd798cb21d..71eacaaacf4a0 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -265,7 +265,7 @@ function pushmeta!(ex::Expr, sym::Symbol, args::Any...) if isempty(args) tag = sym else - tag = Expr(sym, args...) + tag = Expr(sym, args...)::Expr end inner = ex @@ -277,7 +277,7 @@ function pushmeta!(ex::Expr, sym::Symbol, args::Any...) if idx != 0 push!(exargs[idx].args, tag) else - body::Expr = inner.args[2] + body = inner.args[2]::Expr pushfirst!(body.args, Expr(:meta, tag)) end ex @@ -333,7 +333,7 @@ end function findmeta(ex::Expr) if ex.head === :function || is_short_function_def(ex) || ex.head === :-> - body::Expr = ex.args[2] + body = ex.args[2]::Expr body.head === :block || error(body, " is not a block expression") return findmeta_block(ex.args) end diff --git a/base/fastmath.jl b/base/fastmath.jl index 8d36e6e7b5653..c066969349e61 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -118,7 +118,7 @@ function make_fastmath(expr::Expr) end end end - Expr(make_fastmath(expr.head), map(make_fastmath, expr.args)...) + Expr(make_fastmath(expr.head), Base.mapany(make_fastmath, expr.args)...) end function make_fastmath(symb::Symbol) fast_symb = get(fast_op, symb, :nothing) diff --git a/base/views.jl b/base/views.jl index eebd1f31b6980..b82513d73ed8b 100644 --- a/base/views.jl +++ b/base/views.jl @@ -148,10 +148,10 @@ function _views(ex::Expr) # but still use views for the args of the ref: lhs = ex.args[1] Expr(ex.head, Meta.isexpr(lhs, :ref) ? - Expr(:ref, _views.(lhs.args)...) : _views(lhs), + Expr(:ref, mapany(_views, lhs.args)...) : _views(lhs), _views(ex.args[2])) elseif ex.head === :ref - Expr(:call, maybeview, _views.(ex.args)...) + Expr(:call, maybeview, mapany(_views, ex.args)...) else h = string(ex.head) # don't use view on the lhs of an op-assignment a[i...] += ... @@ -182,9 +182,9 @@ function _views(ex::Expr) Expr(first(h) == '.' ? :(.=) : :(=), :($a[$(I...)]), Expr(:call, Symbol(h[1:end-1]), :($maybeview($a, $(I...))), - _views.(ex.args[2:end])...))) + mapany(_views, ex.args[2:end])...))) else - Expr(ex.head, _views.(ex.args)...) + Expr(ex.head, mapany(_views, ex.args)...) end end end diff --git a/stdlib/Markdown/src/Julia/interp.jl b/stdlib/Markdown/src/Julia/interp.jl index 50e51f0f90696..7cd8cdc050124 100644 --- a/stdlib/Markdown/src/Julia/interp.jl +++ b/stdlib/Markdown/src/Julia/interp.jl @@ -39,7 +39,7 @@ end toexpr(x) = x -toexpr(xs::Vector{Any}) = Expr(:call, GlobalRef(Base,:getindex), Any, map(toexpr, xs)...) +toexpr(xs::Vector{Any}) = Expr(:call, GlobalRef(Base,:getindex), Any, mapany(toexpr, xs)...) for T in Any[MD, Paragraph, Header, Link, Bold, Italic] @eval function toexpr(md::$T) diff --git a/stdlib/Markdown/src/Markdown.jl b/stdlib/Markdown/src/Markdown.jl index 8752542bbd445..781fcbdafddc8 100644 --- a/stdlib/Markdown/src/Markdown.jl +++ b/stdlib/Markdown/src/Markdown.jl @@ -5,7 +5,7 @@ Tools for working with the Markdown file format. Mainly for documentation. """ module Markdown -import Base: show, ==, with_output_color +import Base: show, ==, with_output_color, mapany using Base64: stringmime # Margin for printing in terminal. diff --git a/stdlib/Markdown/src/parse/config.jl b/stdlib/Markdown/src/parse/config.jl index 0daf36b3c2442..6cf2f145a6b63 100644 --- a/stdlib/Markdown/src/parse/config.jl +++ b/stdlib/Markdown/src/parse/config.jl @@ -76,7 +76,7 @@ const flavors = Dict{Symbol, Config}() macro flavor(name, features) quote - const $(esc(name)) = config($(map(esc,features.args)...)) + const $(esc(name)) = config($(mapany(esc,features.args)...)) flavors[$(Expr(:quote, name))] = $(esc(name)) end end From b4e51281f9134c9a1b198e95da7facfcbb9f538c Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 23 May 2020 08:04:47 -0500 Subject: [PATCH 8/8] Hide CoreLogging.catch_exceptions behind runtime dispatch --- base/logging.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/logging.jl b/base/logging.jl index a9618af5d94c9..9e1b29fd544fc 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -80,6 +80,7 @@ end _invoked_min_enabled_level(@nospecialize(logger)) = invoke(min_enabled_level, Tuple{typeof(logger)}, logger) +_invoked_catch_exceptions(@nospecialize(logger)) = invoke(catch_exceptions, Tuple{typeof(logger)}, logger) """ NullLogger() @@ -349,7 +350,7 @@ end # Report an error in log message creation (or in the logger itself). @noinline function logging_error(logger, level, _module, group, id, filepath, line, @nospecialize(err)) - if !catch_exceptions(logger) + if !_invoked_catch_exceptions(logger) rethrow(err) end try