Skip to content

Commit 0abe143

Browse files
dlfivefiftystaticfloat
authored andcommitted
Fixes for non-Int based lengths (#37741)
(cherry picked from commit e2f4073)
1 parent cbd17d6 commit 0abe143

File tree

8 files changed

+97
-21
lines changed

8 files changed

+97
-21
lines changed

base/abstractarray.jl

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ julia> axes(A)
8686
"""
8787
function axes(A)
8888
@_inline_meta
89-
map(OneTo, size(A))
89+
map(oneto, size(A))
9090
end
9191

9292
"""
@@ -107,10 +107,10 @@ require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError
107107
# in other applications.
108108
axes1(A::AbstractArray{<:Any,0}) = OneTo(1)
109109
axes1(A::AbstractArray) = (@_inline_meta; axes(A)[1])
110-
axes1(iter) = OneTo(length(iter))
110+
axes1(iter) = oneto(length(iter))
111111

112112
unsafe_indices(A) = axes(A)
113-
unsafe_indices(r::AbstractRange) = (OneTo(unsafe_length(r)),) # Ranges use checked_sub for size
113+
unsafe_indices(r::AbstractRange) = (oneto(unsafe_length(r)),) # Ranges use checked_sub for size
114114

115115
keys(a::AbstractArray) = CartesianIndices(axes(a))
116116
keys(a::AbstractVector) = LinearIndices(a)
@@ -308,7 +308,7 @@ function eachindex(A::AbstractArray, B::AbstractArray...)
308308
@_inline_meta
309309
eachindex(IndexStyle(A,B...), A, B...)
310310
end
311-
eachindex(::IndexLinear, A::AbstractArray) = (@_inline_meta; OneTo(length(A)))
311+
eachindex(::IndexLinear, A::AbstractArray) = (@_inline_meta; oneto(length(A)))
312312
eachindex(::IndexLinear, A::AbstractVector) = (@_inline_meta; axes1(A))
313313
function eachindex(::IndexLinear, A::AbstractArray, B::AbstractArray...)
314314
@_inline_meta
@@ -1481,12 +1481,11 @@ vcat(V::AbstractVector{T}...) where {T} = typed_vcat(T, V...)
14811481
# but that solution currently fails (see #27188 and #27224)
14821482
AbstractVecOrTuple{T} = Union{AbstractVector{<:T}, Tuple{Vararg{T}}}
14831483

1484-
function _typed_vcat(::Type{T}, V::AbstractVecOrTuple{AbstractVector}) where T
1485-
n = 0
1486-
for Vk in V
1487-
n += Int(length(Vk))::Int
1488-
end
1489-
a = similar(V[1], T, n)
1484+
_typed_vcat_similar(V, T, n) = similar(V[1], T, n)
1485+
_typed_vcat(::Type{T}, V::AbstractVecOrTuple{AbstractVector}) where T =
1486+
_typed_vcat!(_typed_vcat_similar(V, T, mapreduce(length, +, V)), V)
1487+
1488+
function _typed_vcat!(a::AbstractVector{T}, V::AbstractVecOrTuple{AbstractVector}) where T
14901489
pos = 1
14911490
for k=1:Int(length(V))::Int
14921491
Vk = V[k]
@@ -1632,15 +1631,15 @@ _cat(dims, X...) = cat_t(promote_eltypeof(X...), X...; dims=dims)
16321631
@inline cat_t(::Type{T}, X...; dims) where {T} = _cat_t(dims, T, X...)
16331632
@inline function _cat_t(dims, ::Type{T}, X...) where {T}
16341633
catdims = dims2cat(dims)
1635-
shape = cat_shape(catdims, map(cat_size, X)::Tuple{Vararg{Union{Int,Dims}}})::Dims
1634+
shape = cat_shape(catdims, map(cat_size, X))
16361635
A = cat_similar(X[1], T, shape)
16371636
if count(!iszero, catdims)::Int > 1
16381637
fill!(A, zero(T))
16391638
end
16401639
return __cat(A, shape, catdims, X...)
16411640
end
16421641

1643-
function __cat(A, shape::NTuple{M,Int}, catdims, X...) where M
1642+
function __cat(A, shape::NTuple{M}, catdims, X...) where M
16441643
N = M::Int
16451644
offsets = zeros(Int, N)
16461645
inds = Vector{UnitRange{Int}}(undef, N)

base/arrayshow.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Alignment is reported as a vector of (left,right) tuples, one for each
5858
column going across the screen.
5959
"""
6060
function alignment(io::IO, X::AbstractVecOrMat,
61-
rows::AbstractVector, cols::AbstractVector,
62-
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer)
63-
a = Tuple{Int, Int}[]
61+
rows::AbstractVector{T}, cols::AbstractVector{V},
62+
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer) where {T,V}
63+
a = Tuple{T, V}[]
6464
for j in cols # need to go down each column one at a time
6565
l = r = 0
6666
for i in rows # plumb down and see what largest element sizes are
@@ -166,6 +166,11 @@ function print_matrix(io::IO, @nospecialize(X::AbstractVecOrMat),
166166
vdots::AbstractString = "\u22ee",
167167
ddots::AbstractString = " \u22f1 ",
168168
hmod::Integer = 5, vmod::Integer = 5)
169+
# use invokelatest to avoid backtracing in type invalidation, ref #37741
170+
invokelatest(_print_matrix, io, X, pre, sep, post, hdots, vdots, ddots, hmod, vmod, unitrange(axes(X,1)), unitrange(axes(X,2)))
171+
end
172+
173+
function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, rowsA, colsA)
169174
hmod, vmod = Int(hmod)::Int, Int(vmod)::Int
170175
if !(get(io, :limit, false)::Bool)
171176
screenheight = screenwidth = typemax(Int)
@@ -178,7 +183,6 @@ function print_matrix(io::IO, @nospecialize(X::AbstractVecOrMat),
178183
postsp = ""
179184
@assert textwidth(hdots) == textwidth(ddots)
180185
sepsize = length(sep)::Int
181-
rowsA, colsA = UnitRange{Int}(axes(X,1)), UnitRange{Int}(axes(X,2))
182186
m, n = length(rowsA), length(colsA)
183187
# To figure out alignments, only need to look at as many rows as could
184188
# fit down screen. If screen has at least as many rows as A, look at A.

base/range.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ unitrange_last(start::T, stop::T) where {T} =
295295
ifelse(stop >= start, convert(T,start+floor(stop-start)),
296296
convert(T,start-oneunit(stop-start)))
297297

298+
unitrange(x) = UnitRange(x)
299+
298300
if isdefined(Main, :Base)
299301
# Constant-fold-able indexing into tuples to functionally expose Base.tail and Base.front
300302
function getindex(@nospecialize(t::Tuple), r::UnitRange)
@@ -332,6 +334,7 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T}
332334
end
333335
OneTo(stop::T) where {T<:Integer} = OneTo{T}(stop)
334336
OneTo(r::AbstractRange{T}) where {T<:Integer} = OneTo{T}(r)
337+
oneto(r) = OneTo(r)
335338

336339
## Step ranges parameterized by length
337340

base/reshapedarray.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ rdims(out::Tuple{}, inds::NTuple{M,Any}) where {M} = ()
153153
rdims(out::Tuple{Any}, inds::Tuple{}) = out # N == 1, M == 0
154154
rdims(out::NTuple{N,Any}, inds::Tuple{}) where {N} = out # N > 1, M == 0
155155
rdims(out::Tuple{Any}, inds::Tuple{Any}) = inds # N == 1, M == 1
156-
rdims(out::Tuple{Any}, inds::NTuple{M,Any}) where {M} = (OneTo(rdims_trailing(inds...)),) # N == 1, M > 1
156+
rdims(out::Tuple{Any}, inds::NTuple{M,Any}) where {M} = (oneto(rdims_trailing(inds...)),) # N == 1, M > 1
157157
rdims(out::NTuple{N,Any}, inds::NTuple{N,Any}) where {N} = inds # N > 1, M == N
158158
rdims(out::NTuple{N,Any}, inds::NTuple{M,Any}) where {N,M} = (first(inds), rdims(tail(out), tail(inds))...) # N > 1, M > 1, M != N
159159

@@ -207,7 +207,7 @@ size(A::ReshapedArray) = A.dims
207207
similar(A::ReshapedArray, eltype::Type, dims::Dims) = similar(parent(A), eltype, dims)
208208
IndexStyle(::Type{<:ReshapedArrayLF}) = IndexLinear()
209209
parent(A::ReshapedArray) = A.parent
210-
parentindices(A::ReshapedArray) = map(OneTo, size(parent(A)))
210+
parentindices(A::ReshapedArray) = map(oneto, size(parent(A)))
211211
reinterpret(::Type{T}, A::ReshapedArray, dims::Dims) where {T} = reinterpret(T, parent(A), dims)
212212
elsize(::Type{<:ReshapedArray{<:Any,<:Any,P}}) where {P} = elsize(P)
213213

base/subarray.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ viewindexing(I::Tuple{Vararg{Any}}) = IndexCartesian()
6060
viewindexing(I::Tuple{AbstractArray, Vararg{Any}}) = IndexCartesian()
6161

6262
# Simple utilities
63-
size(V::SubArray) = (@_inline_meta; map(n->Int(unsafe_length(n)), axes(V)))
63+
size(V::SubArray) = (@_inline_meta; map(unsafe_length, axes(V)))
6464

6565
similar(V::SubArray, T::Type, dims::Dims) = similar(V.parent, T, dims)
6666

@@ -90,7 +90,7 @@ julia> parentindices(V)
9090
(1, Base.Slice(Base.OneTo(2)))
9191
```
9292
"""
93-
parentindices(a::AbstractArray) = map(OneTo, size(a))
93+
parentindices(a::AbstractArray) = map(oneto, size(a))
9494

9595
## Aliasing detection
9696
dataids(A::SubArray) = (dataids(A.parent)..., _splatmap(dataids, A.indices)...)
@@ -107,7 +107,7 @@ function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Varar
107107
end
108108
# Transform indices to be "dense"
109109
_trimmedindex(i::Real) = oftype(i, 1)
110-
_trimmedindex(i::AbstractUnitRange) = oftype(i, OneTo(length(i)))
110+
_trimmedindex(i::AbstractUnitRange) = oftype(i, oneto(length(i)))
111111
_trimmedindex(i::AbstractArray) = oftype(i, reshape(eachindex(IndexLinear(), i), axes(i)))
112112

113113
## SubArray creation

test/abstractarray.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,3 +1219,8 @@ end
12191219
_, st = iterate(a)
12201220
@test Base.rest(a, st) == [3, 2, 4]
12211221
end
1222+
1223+
@testset "issue #37741, non-int cat" begin
1224+
@test [1; 1:BigInt(5)] == [1; 1:5]
1225+
@test [1:BigInt(5); 1] == [1:5; 1]
1226+
end

test/subarray.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,3 +698,17 @@ import InteractiveUtils
698698
@test M*v == copy(M)*v
699699
@test (InteractiveUtils.@which M*v) == (InteractiveUtils.@which copy(M)*v)
700700
end
701+
702+
703+
isdefined(Main, :InfiniteArrays) || @eval Main include("testhelpers/InfiniteArrays.jl")
704+
using .Main.InfiniteArrays, Base64
705+
706+
@testset "PR #37741: non-Int sizes" begin
707+
r = BigInt(1):BigInt(100_000_000)^100
708+
v = SubArray(r, (r,))
709+
@test size(v) == (last(r),)
710+
711+
v = SubArray(OneToInf(), (OneToInf(),))
712+
@test size(v) == (Infinity(),)
713+
@test stringmime("text/plain", v; context=(:limit => true)) == "$(Infinity())-element view(::$(OneToInf{Int}), 1:1:$(Infinity())) with eltype $Int with indices 1:1:$(Infinity()):\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n"
714+
end

test/testhelpers/InfiniteArrays.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
# InfiniteArrays (arrays with infinite size)
4+
5+
# This test file is designed to exercise support for generic sizing,
6+
# even though infinite arrays aren't implemented in Base.
7+
8+
module InfiniteArrays
9+
10+
export OneToInf, Infinity
11+
12+
"""
13+
Infinity()
14+
15+
represents infinite cardinality. Note that `Infinity <: Integer` to support
16+
being treated as an index.
17+
"""
18+
struct Infinity <: Integer end
19+
20+
Base.:(==)(::Infinity, ::Int) = false
21+
Base.:(==)(::Int, ::Infinity) = false
22+
Base.:(<)(::Int, ::Infinity) = true
23+
Base.:()(::Int, ::Infinity) = true
24+
Base.:()(::Infinity, ::Int) = false
25+
Base.:()(::Infinity, ::Infinity) = true
26+
Base.:(-)(::Infinity, ::Int) = Infinity()
27+
Base.:(+)(::Infinity, ::Int) = Infinity()
28+
Base.:(:)(::Infinity, ::Infinity) = 1:0
29+
30+
"""
31+
OneToInf(n)
32+
33+
Define an `AbstractInfUnitRange` that behaves like `1:∞`, with the added
34+
distinction that the limits are guaranteed (by the type system) to
35+
be 1 and ∞.
36+
"""
37+
struct OneToInf{T<:Integer} <: AbstractUnitRange{T} end
38+
39+
OneToInf() = OneToInf{Int}()
40+
41+
Base.axes(r::OneToInf) = (r,)
42+
Base.unsafe_indices(r::OneToInf) = (r,)
43+
Base.unsafe_length(r::OneToInf) = Infinity()
44+
Base.size(r::OneToInf) = (Infinity(),)
45+
Base.first(r::OneToInf{T}) where {T} = oneunit(T)
46+
Base.length(r::OneToInf{T}) where {T} = Infinity()
47+
Base.last(r::OneToInf{T}) where {T} = Infinity()
48+
Base.unitrange(r::OneToInf) = r
49+
Base.oneto(::Infinity) = OneToInf()
50+
51+
end

0 commit comments

Comments
 (0)