Skip to content

Commit e2377f1

Browse files
timholyvtjnash
andauthored
Various inferrability improvements (#41917)
- two functions affected by `Core.Box` (#15276) were ameliorated - type info added to the `stack` field of `ExceptionStack` - avoid unknown dispatch from de-specialized code Co-authored-by: Jameson Nash <[email protected]>
1 parent e2aeefb commit e2377f1

File tree

7 files changed

+61
-51
lines changed

7 files changed

+61
-51
lines changed

base/arrayshow.jl

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ column going across the screen.
5959
"""
6060
function alignment(io::IO, @nospecialize(X::AbstractVecOrMat),
6161
rows::AbstractVector{T}, cols::AbstractVector{V},
62-
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer) where {T,V}
62+
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer,
63+
#= `size(X) may not infer, set this in caller =# ncols::Integer=size(X, 2)) where {T,V}
6364
a = Tuple{T, V}[]
6465
for j in cols # need to go down each column one at a time
6566
l = r = 0
@@ -78,7 +79,7 @@ function alignment(io::IO, @nospecialize(X::AbstractVecOrMat),
7879
break
7980
end
8081
end
81-
if 1 < length(a) < length(axes(X,2))
82+
if 1 < length(a) < ncols
8283
while sum(map(sum,a)) + sep*length(a) >= cols_otherwise
8384
pop!(a)
8485
end
@@ -95,7 +96,8 @@ is specified as string sep.
9596
"""
9697
function print_matrix_row(io::IO,
9798
@nospecialize(X::AbstractVecOrMat), A::Vector,
98-
i::Integer, cols::AbstractVector, sep::AbstractString)
99+
i::Integer, cols::AbstractVector, sep::AbstractString,
100+
#= `axes(X)` may not infer, set this in caller =# idxlast::Integer=last(axes(X, 2)))
99101
for (k, j) = enumerate(cols)
100102
k > length(A) && break
101103
if isassigned(X,Int(i),Int(j)) # isassigned accepts only `Int` indices
@@ -114,7 +116,7 @@ function print_matrix_row(io::IO,
114116
sx = undef_ref_str
115117
end
116118
l = repeat(" ", A[k][1]-a[1]) # pad on left and right as needed
117-
r = j == axes(X, 2)[end] ? "" : repeat(" ", A[k][2]-a[2])
119+
r = j == idxlast ? "" : repeat(" ", A[k][2]-a[2])
118120
prettysx = replace_in_print_matrix(X,i,j,sx)
119121
print(io, l, prettysx, r)
120122
if k < length(A); print(io, sep); end
@@ -171,6 +173,7 @@ end
171173

172174
function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, rowsA, colsA)
173175
hmod, vmod = Int(hmod)::Int, Int(vmod)::Int
176+
ncols, idxlast = length(colsA), last(colsA)
174177
if !(get(io, :limit, false)::Bool)
175178
screenheight = screenwidth = typemax(Int)
176179
else
@@ -201,26 +204,26 @@ function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, h
201204
else
202205
colsA = [colsA;]
203206
end
204-
A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize)
207+
A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize, ncols)
205208
# Nine-slicing is accomplished using print_matrix_row repeatedly
206209
if m <= screenheight # rows fit vertically on screen
207210
if n <= length(A) # rows and cols fit so just print whole matrix in one piece
208211
for i in rowsA
209212
print(io, i == first(rowsA) ? pre : presp)
210-
print_matrix_row(io, X,A,i,colsA,sep)
213+
print_matrix_row(io, X,A,i,colsA,sep,idxlast)
211214
print(io, i == last(rowsA) ? post : postsp)
212215
if i != last(rowsA); println(io); end
213216
end
214217
else # rows fit down screen but cols don't, so need horizontal ellipsis
215218
c = div(screenwidth-length(hdots)::Int+1,2)+1 # what goes to right of ellipsis
216-
Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize)) # alignments for right
219+
Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize, ncols)) # alignments for right
217220
c = screenwidth - sum(map(sum,Ralign)) - (length(Ralign)-1)*sepsize - length(hdots)::Int
218-
Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize) # alignments for left of ellipsis
221+
Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize, ncols) # alignments for left of ellipsis
219222
for i in rowsA
220223
print(io, i == first(rowsA) ? pre : presp)
221-
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep)
224+
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep,idxlast)
222225
print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)::Int))
223-
print_matrix_row(io, X, Ralign, i, (n - length(Ralign)) .+ colsA, sep)
226+
print_matrix_row(io, X, Ralign, i, (n - length(Ralign)) .+ colsA, sep, idxlast)
224227
print(io, i == last(rowsA) ? post : postsp)
225228
if i != last(rowsA); println(io); end
226229
end
@@ -229,7 +232,7 @@ function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, h
229232
if n <= length(A) # rows don't fit, cols do, so only vertical ellipsis
230233
for i in rowsA
231234
print(io, i == first(rowsA) ? pre : presp)
232-
print_matrix_row(io, X,A,i,colsA,sep)
235+
print_matrix_row(io, X,A,i,colsA,sep,idxlast)
233236
print(io, i == last(rowsA) ? post : postsp)
234237
if i != rowsA[end] || i == rowsA[halfheight]; println(io); end
235238
if i == rowsA[halfheight]
@@ -240,15 +243,15 @@ function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, h
240243
end
241244
else # neither rows nor cols fit, so use all 3 kinds of dots
242245
c = div(screenwidth-length(hdots)::Int+1,2)+1
243-
Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize))
246+
Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize, ncols))
244247
c = screenwidth - sum(map(sum,Ralign)) - (length(Ralign)-1)*sepsize - length(hdots)::Int
245-
Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize)
248+
Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize, ncols)
246249
r = mod((length(Ralign)-n+1),vmod) # where to put dots on right half
247250
for i in rowsA
248251
print(io, i == first(rowsA) ? pre : presp)
249-
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep)
252+
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep,idxlast)
250253
print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)::Int))
251-
print_matrix_row(io, X,Ralign,i,(n-length(Ralign)).+colsA,sep)
254+
print_matrix_row(io, X,Ralign,i,(n-length(Ralign)).+colsA,sep,idxlast)
252255
print(io, i == last(rowsA) ? post : postsp)
253256
if i != rowsA[end] || i == rowsA[halfheight]; println(io); end
254257
if i == rowsA[halfheight]

base/error.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ function catch_backtrace()
124124
end
125125

126126
struct ExceptionStack <: AbstractArray{Any,1}
127-
stack
127+
stack::Array{Any,1}
128128
end
129129

130130
"""

base/range.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -615,22 +615,23 @@ function print_range(io::IO, r::AbstractRange,
615615
maxpossiblecols = div(screenwidth, 1+sepsize) # assume each element is at least 1 char + 1 separator
616616
colsr = n <= maxpossiblecols ? (1:n) : [1:div(maxpossiblecols,2)+1; (n-div(maxpossiblecols,2)):n]
617617
rowmatrix = reshape(r[colsr], 1, length(colsr)) # treat the range as a one-row matrix for print_matrix_row
618-
A = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), screenwidth, screenwidth, sepsize) # how much space range takes
618+
nrow, idxlast = size(rowmatrix, 2), last(axes(rowmatrix, 2))
619+
A = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), screenwidth, screenwidth, sepsize, nrow) # how much space range takes
619620
if n <= length(A) # cols fit screen, so print out all elements
620621
print(io, pre) # put in pre chars
621-
print_matrix_row(io,rowmatrix,A,1,1:n,sep) # the entire range
622+
print_matrix_row(io,rowmatrix,A,1,1:n,sep,idxlast) # the entire range
622623
print(io, post) # add the post characters
623624
else # cols don't fit so put horiz ellipsis in the middle
624625
# how many chars left after dividing width of screen in half
625626
# and accounting for the horiz ellipsis
626627
c = div(screenwidth-length(hdots)+1,2)+1 # chars remaining for each side of rowmatrix
627-
alignR = reverse(alignment(io, rowmatrix, 1:m, length(rowmatrix):-1:1, c, c, sepsize)) # which cols of rowmatrix to put on the right
628+
alignR = reverse(alignment(io, rowmatrix, 1:m, length(rowmatrix):-1:1, c, c, sepsize, nrow)) # which cols of rowmatrix to put on the right
628629
c = screenwidth - sum(map(sum,alignR)) - (length(alignR)-1)*sepsize - length(hdots)
629-
alignL = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), c, c, sepsize) # which cols of rowmatrix to put on the left
630+
alignL = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), c, c, sepsize, nrow) # which cols of rowmatrix to put on the left
630631
print(io, pre) # put in pre chars
631-
print_matrix_row(io, rowmatrix,alignL,1,1:length(alignL),sep) # left part of range
632+
print_matrix_row(io, rowmatrix,alignL,1,1:length(alignL),sep,idxlast) # left part of range
632633
print(io, hdots) # horizontal ellipsis
633-
print_matrix_row(io, rowmatrix,alignR,1,length(rowmatrix)-length(alignR)+1:length(rowmatrix),sep) # right part of range
634+
print_matrix_row(io, rowmatrix,alignR,1,length(rowmatrix)-length(alignR)+1:length(rowmatrix),sep,idxlast) # right part of range
634635
print(io, post) # post chars
635636
end
636637
end

contrib/generate_precompile.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ function generate_precompile_statements()
377377
# XXX: precompile doesn't currently handle overloaded Vararg arguments very well.
378378
# Replacing N with a large number works around it.
379379
l = l.args[end]
380-
if isexpr(l, :curly) && length(l.args) == 2 && l.args[1] == :Vararg # Vararg{T}
380+
if isexpr(l, :curly) && length(l.args) == 2 && l.args[1] === :Vararg # Vararg{T}
381381
push!(l.args, 100) # form Vararg{T, 100} instead
382382
end
383383
end

stdlib/Logging/src/ConsoleLogger.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function default_metafmt(level::LogLevel, _module, group, id, file, line)
7070
prefix = string(level == Warn ? "Warning" : string(level), ':')
7171
suffix::String = ""
7272
Info <= level < Warn && return color, prefix, suffix
73-
_module !== nothing && (suffix *= "$(_module)")
73+
_module !== nothing && (suffix *= string(_module)::String)
7474
if file !== nothing
7575
_module !== nothing && (suffix *= " ")
7676
suffix *= Base.contractuser(file)::String

stdlib/REPL/src/docview.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,12 @@ function symbol_latex(s::String)
402402

403403
return get(symbols_latex, s, "")
404404
end
405-
function repl_latex(io::IO, s::String)
406-
latex = symbol_latex(s)
405+
function repl_latex(io::IO, s0::String)
406+
# This has rampant `Core.Box` problems (#15276). Use the tricks of
407+
# https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured
408+
# We're changing some of the values so the `let` trick isn't applicable.
409+
s::String = s0
410+
latex::String = symbol_latex(s)
407411
if isempty(latex)
408412
# Decompose NFC-normalized identifier to match tab-completion
409413
# input if the first search came up empty.
@@ -420,7 +424,7 @@ function repl_latex(io::IO, s::String)
420424
print(io, "\"")
421425
printstyled(io, s, color=:cyan)
422426
print(io, "\" can be typed by ")
423-
state = '\0'
427+
state::Char = '\0'
424428
with_output_color(:cyan, io) do io
425429
for c in s
426430
cstr = string(c)

stdlib/Test/src/Test.jl

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,30 +1580,32 @@ function _inferred(ex, mod, allow = :(Union{}))
15801580
ex = Expr(:call, GlobalRef(Test, :_materialize_broadcasted),
15811581
farg, ex.args[2:end]...)
15821582
end
1583-
Base.remove_linenums!(quote
1584-
let
1585-
allow = $(esc(allow))
1586-
allow isa Type || throw(ArgumentError("@inferred requires a type as second argument"))
1587-
$(if any(a->(Meta.isexpr(a, :kw) || Meta.isexpr(a, :parameters)), ex.args)
1588-
# Has keywords
1589-
args = gensym()
1590-
kwargs = gensym()
1591-
quote
1592-
$(esc(args)), $(esc(kwargs)), result = $(esc(Expr(:call, _args_and_call, ex.args[2:end]..., ex.args[1])))
1593-
inftypes = $(gen_call_with_extracted_types(mod, Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...))))
1594-
end
1595-
else
1596-
# No keywords
1597-
quote
1598-
args = ($([esc(ex.args[i]) for i = 2:length(ex.args)]...),)
1599-
result = $(esc(ex.args[1]))(args...)
1600-
inftypes = Base.return_types($(esc(ex.args[1])), Base.typesof(args...))
1601-
end
1602-
end)
1603-
@assert length(inftypes) == 1
1604-
rettype = result isa Type ? Type{result} : typeof(result)
1605-
rettype <: allow || rettype == typesplit(inftypes[1], allow) || error("return type $rettype does not match inferred return type $(inftypes[1])")
1606-
result
1583+
Base.remove_linenums!(let ex = ex;
1584+
quote
1585+
let
1586+
allow = $(esc(allow))
1587+
allow isa Type || throw(ArgumentError("@inferred requires a type as second argument"))
1588+
$(if any(a->(Meta.isexpr(a, :kw) || Meta.isexpr(a, :parameters)), ex.args)
1589+
# Has keywords
1590+
args = gensym()
1591+
kwargs = gensym()
1592+
quote
1593+
$(esc(args)), $(esc(kwargs)), result = $(esc(Expr(:call, _args_and_call, ex.args[2:end]..., ex.args[1])))
1594+
inftypes = $(gen_call_with_extracted_types(mod, Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...))))
1595+
end
1596+
else
1597+
# No keywords
1598+
quote
1599+
args = ($([esc(ex.args[i]) for i = 2:length(ex.args)]...),)
1600+
result = $(esc(ex.args[1]))(args...)
1601+
inftypes = Base.return_types($(esc(ex.args[1])), Base.typesof(args...))
1602+
end
1603+
end)
1604+
@assert length(inftypes) == 1
1605+
rettype = result isa Type ? Type{result} : typeof(result)
1606+
rettype <: allow || rettype == typesplit(inftypes[1], allow) || error("return type $rettype does not match inferred return type $(inftypes[1])")
1607+
result
1608+
end
16071609
end
16081610
end)
16091611
end

0 commit comments

Comments
 (0)