From 03d9390b5fb29ebd17131b14cb251c7676c72869 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 12 Nov 2021 10:42:42 -0500 Subject: [PATCH] ranges: fix empty length for smallints (#43042) Fixes #29801 (cherry picked from commit b71330de9847e46ea7033a8267c5a56025ffefdb) --- base/range.jl | 7 ++++++- test/ranges.jl | 14 ++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/base/range.jl b/base/range.jl index 07d9f598d4339..bb5a17f4d4a5a 100644 --- a/base/range.jl +++ b/base/range.jl @@ -754,7 +754,12 @@ let smallints = (Int === Int64 ? Union{Int8, UInt8, Int16, UInt16}) global length, checked_length # n.b. !(step isa T) - length(r::OrdinalRange{<:smallints}) = div(Int(last(r)) - Int(first(r)), step(r)) + 1 + function length(r::OrdinalRange{<:smallints}) + s = step(r) + s == zero(s) && return 0 # unreachable, by construction, but avoids the error case here later + isempty(r) && return 0 + return div(Int(last(r)) - Int(first(r)), s) + 1 + end length(r::AbstractUnitRange{<:smallints}) = Int(last(r)) - Int(first(r)) + 1 length(r::OneTo{<:smallints}) = Int(r.stop) checked_length(r::OrdinalRange{<:smallints}) = length(r) diff --git a/test/ranges.jl b/test/ranges.jl index e0558ff75b0b7..b39dff7506061 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1014,13 +1014,19 @@ end @test length(map(identity, UInt64(1):UInt64(5))) == 5 @test length(map(identity, UInt128(1):UInt128(5))) == 5 end -@testset "issue #8531" begin +@testset "issue #8531, issue #29801" begin smallint = (Int === Int64 ? - (Int8,UInt8,Int16,UInt16,Int32,UInt32) : - (Int8,UInt8,Int16,UInt16)) + (Int8, UInt8, Int16, UInt16, Int32, UInt32) : + (Int8, UInt8, Int16, UInt16)) for T in smallint s = typemin(T):typemax(T) - @test length(s) == checked_length(s) == 2^(8*sizeof(T)) + @test length(s) === checked_length(s) === 2^(8*sizeof(T)) + s = T(10):typemax(T):T(10) + @test length(s) === checked_length(s) === 1 + s = T(10):typemax(T):T(0) + @test length(s) === checked_length(s) === 0 + s = T(10):typemax(T):typemin(T) + @test length(s) === checked_length(s) === 0 end end