From c332e901869d6c5f9c212d3a5670b59f32609683 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 17 Jul 2023 16:40:02 +0530 Subject: [PATCH 1/2] Array(::AbstractRange) should return an Array --- base/range.jl | 12 ++++++++++-- test/ranges.jl | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/base/range.jl b/base/range.jl index 9f5dd214d67bb..d350e23954d5f 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1377,8 +1377,16 @@ function vcat(rs::AbstractRange{T}...) where T return a end -Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r) -collect(r::AbstractRange) = vcat(r) +function Array{T,1}(r::AbstractRange{T}) where {T} + a = Vector{T}(undef, length(r)) + i = 1 + for x in r + @inbounds a[i] = x + i += 1 + end + return a +end +collect(r::AbstractRange) = Array(r) _reverse(r::OrdinalRange, ::Colon) = (:)(last(r), negate(step(r)), first(r)) function _reverse(r::StepRangeLen, ::Colon) diff --git a/test/ranges.jl b/test/ranges.jl index 0e195f5dde24e..c9bbdce70e904 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1802,6 +1802,7 @@ Base.div(x::Displacement, y::Displacement) = Displacement(div(x.val, y.val)) # required for collect (summing lengths); alternatively, should length return Int by default? Base.promote_rule(::Type{Displacement}, ::Type{Int}) = Int Base.convert(::Type{Int}, x::Displacement) = x.val +Base.Int(x::Displacement) = x.val # Unsigned complement, for testing checked_length struct UPosition <: Unsigned @@ -2498,3 +2499,22 @@ end # a case that using mul_with_overflow & add_with_overflow might get wrong: @test (-10:2:typemax(Int))[typemax(Int)รท2+2] == typemax(Int)-9 end + +@testset "collect with specialized vcat" begin + struct OneToThree <: AbstractUnitRange{Int} end + Base.size(r::OneToThree) = (3,) + Base.first(r::OneToThree) = 1 + Base.length(r::OneToThree) = 3 + Base.last(r::OneToThree) = 3 + function Base.getindex(r::OneToThree, i::Int) + checkbounds(r, i) + i + end + Base.vcat(r::OneToThree) = r + r = OneToThree() + a = Array(r) + @test a isa Vector{Int} + @test a == r + @test collect(r) isa Vector{Int} + @test collect(r) == r +end From 1b7bf936febef3c7a022c8a837b60963c217df9c Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 20 Jul 2023 13:15:20 +0530 Subject: [PATCH 2/2] Add comment to Array method --- base/range.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/range.jl b/base/range.jl index 635f921b5c1bd..e8ffe10e2ba7f 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1380,6 +1380,11 @@ function vcat(rs::AbstractRange{T}...) where T return a end +# This method differs from that for AbstractArrays as it +# use iteration instead of indexing. This works even if certain +# non-standard ranges don't support indexing. +# See https://github.com/JuliaLang/julia/pull/27302 +# Similarly, collect(r::AbstractRange) uses iteration function Array{T,1}(r::AbstractRange{T}) where {T} a = Vector{T}(undef, length(r)) i = 1