-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes for non-Int based lengths #37741
Changes from all commits
476a59b
1d8f1fb
433fb9e
a73d161
8bf23e2
e1159be
7179d5d
0cad296
54bcf48
859bc47
9df3e87
3129fbb
3051d7e
69ba1d7
a6ddb9e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,7 @@ julia> axes(A) | |
""" | ||
function axes(A) | ||
@_inline_meta | ||
map(OneTo, size(A)) | ||
map(oneto, size(A)) | ||
end | ||
|
||
""" | ||
|
@@ -107,10 +107,10 @@ require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError | |
# in other applications. | ||
axes1(A::AbstractArray{<:Any,0}) = OneTo(1) | ||
axes1(A::AbstractArray) = (@_inline_meta; axes(A)[1]) | ||
axes1(iter) = OneTo(length(iter)) | ||
axes1(iter) = oneto(length(iter)) | ||
|
||
unsafe_indices(A) = axes(A) | ||
unsafe_indices(r::AbstractRange) = (OneTo(unsafe_length(r)),) # Ranges use checked_sub for size | ||
unsafe_indices(r::AbstractRange) = (oneto(unsafe_length(r)),) # Ranges use checked_sub for size | ||
|
||
keys(a::AbstractArray) = CartesianIndices(axes(a)) | ||
keys(a::AbstractVector) = LinearIndices(a) | ||
|
@@ -308,7 +308,7 @@ function eachindex(A::AbstractArray, B::AbstractArray...) | |
@_inline_meta | ||
eachindex(IndexStyle(A,B...), A, B...) | ||
end | ||
eachindex(::IndexLinear, A::AbstractArray) = (@_inline_meta; OneTo(length(A))) | ||
eachindex(::IndexLinear, A::AbstractArray) = (@_inline_meta; oneto(length(A))) | ||
eachindex(::IndexLinear, A::AbstractVector) = (@_inline_meta; axes1(A)) | ||
function eachindex(::IndexLinear, A::AbstractArray, B::AbstractArray...) | ||
@_inline_meta | ||
|
@@ -1483,12 +1483,11 @@ vcat(V::AbstractVector{T}...) where {T} = typed_vcat(T, V...) | |
# but that solution currently fails (see #27188 and #27224) | ||
AbstractVecOrTuple{T} = Union{AbstractVector{<:T}, Tuple{Vararg{T}}} | ||
|
||
function _typed_vcat(::Type{T}, V::AbstractVecOrTuple{AbstractVector}) where T | ||
n = 0 | ||
for Vk in V | ||
n += Int(length(Vk))::Int | ||
end | ||
a = similar(V[1], T, n) | ||
_typed_vcat_similar(V, T, n) = similar(V[1], T, n) | ||
_typed_vcat(::Type{T}, V::AbstractVecOrTuple{AbstractVector}) where T = | ||
_typed_vcat!(_typed_vcat_similar(V, T, mapreduce(length, +, V)), V) | ||
|
||
function _typed_vcat!(a::AbstractVector{T}, V::AbstractVecOrTuple{AbstractVector}) where T | ||
pos = 1 | ||
for k=1:Int(length(V))::Int | ||
Vk = V[k] | ||
|
@@ -1634,15 +1633,15 @@ _cat(dims, X...) = cat_t(promote_eltypeof(X...), X...; dims=dims) | |
@inline cat_t(::Type{T}, X...; dims) where {T} = _cat_t(dims, T, X...) | ||
@inline function _cat_t(dims, ::Type{T}, X...) where {T} | ||
catdims = dims2cat(dims) | ||
shape = cat_shape(catdims, map(cat_size, X)::Tuple{Vararg{Union{Int,Dims}}})::Dims | ||
shape = cat_shape(catdims, map(cat_size, X)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as comment for |
||
A = cat_similar(X[1], T, shape) | ||
if count(!iszero, catdims)::Int > 1 | ||
fill!(A, zero(T)) | ||
end | ||
return __cat(A, shape, catdims, X...) | ||
end | ||
|
||
function __cat(A, shape::NTuple{M,Int}, catdims, X...) where M | ||
function __cat(A, shape::NTuple{M}, catdims, X...) where M | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
N = M::Int | ||
offsets = zeros(Int, N) | ||
inds = Vector{UnitRange{Int}}(undef, N) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,9 +58,9 @@ Alignment is reported as a vector of (left,right) tuples, one for each | |
column going across the screen. | ||
""" | ||
function alignment(io::IO, X::AbstractVecOrMat, | ||
rows::AbstractVector, cols::AbstractVector, | ||
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer) | ||
a = Tuple{Int, Int}[] | ||
rows::AbstractVector{T}, cols::AbstractVector{V}, | ||
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer) where {T,V} | ||
a = Tuple{T, V}[] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is more concerning. I'm a little surprised that we don't julia> include("/tmp/sv.jl")
2-element SquaresVector:
1
4 0.395123 seconds (1.06 M allocations: 58.098 MiB, 6.47% gc time, 99.91% compilation time) where struct SquaresVector <: AbstractArray{Int, 1}
count::Int
end
Base.size(S::SquaresVector) = (S.count,)
Base.IndexStyle(::Type{<:SquaresVector}) = IndexLinear()
Base.getindex(S::SquaresVector, i::Int) = i*i
sv = SquaresVector(2)
@time show(stdout, MIME("text/plain"), sv) 0.4s is a long time, and we have to pay it if stuff gets invalidated. Since the code_warntype(Base.alignment, (IO, AbstractVecOrMat, AbstractVector, AbstractVector, Integer, Integer, Integer)) and code_warntype(Base.print_matrix, (IO, AbstractVecOrMat, AbstractString, AbstractString, AbstractString, AbstractString, AbstractString, AbstractString, Integer, Integer)) to see the invalidation risks and how much the type-asserts currently save us. You might compare this branch against master and check for differences. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It seems what we want to say is that we are iterating over the "range" of a vector. A more descriptive way would be to change it to julia> union(Base.OneTo(5))
5-element Vector{Int64}:
1
2
3
4
5 There's a very good argument for adding special overloads for |
||
for j in cols # need to go down each column one at a time | ||
l = r = 0 | ||
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), | |
vdots::AbstractString = "\u22ee", | ||
ddots::AbstractString = " \u22f1 ", | ||
hmod::Integer = 5, vmod::Integer = 5) | ||
# use invokelatest to avoid backtracing in type invalidation, ref #37741 | ||
invokelatest(_print_matrix, io, X, pre, sep, post, hdots, vdots, ddots, hmod, vmod, unitrange(axes(X,1)), unitrange(axes(X,2))) | ||
end | ||
|
||
function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, rowsA, colsA) | ||
hmod, vmod = Int(hmod)::Int, Int(vmod)::Int | ||
if !(get(io, :limit, false)::Bool) | ||
screenheight = screenwidth = typemax(Int) | ||
|
@@ -178,7 +183,6 @@ function print_matrix(io::IO, @nospecialize(X::AbstractVecOrMat), | |
postsp = "" | ||
@assert textwidth(hdots) == textwidth(ddots) | ||
sepsize = length(sep)::Int | ||
rowsA, colsA = UnitRange{Int}(axes(X,1)), UnitRange{Int}(axes(X,2)) | ||
m, n = length(rowsA), length(colsA) | ||
# To figure out alignments, only need to look at as many rows as could | ||
# fit down screen. If screen has at least as many rows as A, look at A. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
# InfiniteArrays (arrays with infinite size) | ||
|
||
# This test file is designed to exercise support for generic sizing, | ||
# even though infinite arrays aren't implemented in Base. | ||
|
||
module InfiniteArrays | ||
|
||
export OneToInf, Infinity | ||
|
||
""" | ||
Infinity() | ||
|
||
represents infinite cardinality. Note that `Infinity <: Integer` to support | ||
being treated as an index. | ||
""" | ||
struct Infinity <: Integer end | ||
|
||
Base.:(==)(::Infinity, ::Int) = false | ||
Base.:(==)(::Int, ::Infinity) = false | ||
Base.:(<)(::Int, ::Infinity) = true | ||
Base.:(≤)(::Int, ::Infinity) = true | ||
Base.:(≤)(::Infinity, ::Int) = false | ||
Base.:(≤)(::Infinity, ::Infinity) = true | ||
Base.:(-)(::Infinity, ::Int) = Infinity() | ||
Base.:(+)(::Infinity, ::Int) = Infinity() | ||
Base.:(:)(::Infinity, ::Infinity) = 1:0 | ||
|
||
""" | ||
OneToInf(n) | ||
|
||
Define an `AbstractInfUnitRange` that behaves like `1:∞`, with the added | ||
distinction that the limits are guaranteed (by the type system) to | ||
be 1 and ∞. | ||
""" | ||
struct OneToInf{T<:Integer} <: AbstractUnitRange{T} end | ||
|
||
OneToInf() = OneToInf{Int}() | ||
|
||
Base.axes(r::OneToInf) = (r,) | ||
Base.unsafe_indices(r::OneToInf) = (r,) | ||
Base.unsafe_length(r::OneToInf) = Infinity() | ||
Base.size(r::OneToInf) = (Infinity(),) | ||
Base.first(r::OneToInf{T}) where {T} = oneunit(T) | ||
Base.length(r::OneToInf{T}) where {T} = Infinity() | ||
Base.last(r::OneToInf{T}) where {T} = Infinity() | ||
Base.unitrange(r::OneToInf) = r | ||
Base.oneto(::Infinity) = OneToInf() | ||
|
||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the perspective of Base & stdlibs, this change seems safe because
_typed_vcat
has no backedges that extend deeper thantyped_vcat
---we expunged them from the system image (probably mostly in #37163). You can create more backedges withvcat(1:3, [1,2,3])
, and so this may cause some worsening of package interactions, but I think that can argued to be their problem rather than Julia's.