Skip to content

Commit

Permalink
Disallow ranges with Integer eltype but non-integer step (JuliaLang#3…
Browse files Browse the repository at this point in the history
  • Loading branch information
sostock committed Nov 30, 2020
1 parent 217a449 commit c31d126
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ New library features
Standard library changes
------------------------

* It is no longer possible to create a `LinRange`, `StepRange`, or `StepRangeLen` with a `<: Integer` eltype but non-integer step ([#32439]).
* `pkg> precompile` is now parallelized through depth-first precompilation of dependencies. Errors will only throw for
direct dependencies listed in the `Project.toml`.
* `pkg> precompile` is now automatically triggered whenever Pkg changes the active manifest. Auto-precompilation will
Expand Down
12 changes: 11 additions & 1 deletion base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ function steprange_last(start::T, step, stop) where T
if isa(start,AbstractFloat) || isa(step,AbstractFloat)
throw(ArgumentError("StepRange should not be used with floating point"))
end
if isa(start,Integer) && !isinteger(start + step)
throw(ArgumentError("StepRange{<:Integer} cannot have non-integer step"))
end
z = zero(step)
step == z && throw(ArgumentError("step cannot be zero"))

Expand Down Expand Up @@ -351,6 +354,9 @@ struct StepRangeLen{T,R,S} <: AbstractRange{T}
offset::Int # the index of ref

function StepRangeLen{T,R,S}(ref::R, step::S, len::Integer, offset::Integer = 1) where {T,R,S}
if T <: Integer && !isinteger(ref + step)
throw(ArgumentError("StepRangeLen{<:Integer} cannot have non-integer step"))
end
len >= 0 || throw(ArgumentError("length cannot be negative, got $len"))
1 <= offset <= max(1,len) || throw(ArgumentError("StepRangeLen: offset must be in [1,$len], got $offset"))
new(ref, step, len, offset)
Expand Down Expand Up @@ -410,7 +416,11 @@ struct LinRange{T} <: AbstractRange{T}
start == stop || throw(ArgumentError("range($start, stop=$stop, length=$len): endpoints differ"))
return new(start, stop, 1, 1)
end
new(start,stop,len,max(len-1,1))
lendiv = max(len-1, 1)
if T <: Integer && !iszero(mod(stop-start, lendiv))
throw(ArgumentError("LinRange{<:Integer} cannot have non-integer step"))
end
new(start,stop,len,lendiv)
end
end

Expand Down
9 changes: 9 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,15 @@ end
@test eltype(['a':'z', 1:2]) == (StepRange{T,Int} where T)
end

@testset "Ranges with <:Integer eltype but non-integer step (issue #32419)" begin
@test eltype(StepRange(1, 1//1, 2)) === Int
@test_throws ArgumentError StepRange(1, 1//2, 2)
@test eltype(StepRangeLen{Int}(1, 1//1, 2)) === Int
@test_throws ArgumentError StepRangeLen{Int}(1, 1//2, 2)
@test eltype(LinRange{Int}(1, 5, 3)) === Int
@test_throws ArgumentError LinRange{Int}(1, 5, 4)
end

@testset "LinRange ops" begin
@test 2*LinRange(0,3,4) == LinRange(0,6,4)
@test LinRange(0,3,4)*2 == LinRange(0,6,4)
Expand Down

0 comments on commit c31d126

Please sign in to comment.