From 904e6a7f949b725a5adbad7c467beed52fb7acc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 25 Apr 2019 14:14:57 +0200 Subject: [PATCH 01/22] An initial proposal to check Bool case --- base/range.jl | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/base/range.jl b/base/range.jl index 9fbc198d1c372..7b4fa0b03047e 100644 --- a/base/range.jl +++ b/base/range.jl @@ -608,6 +608,9 @@ function getindex(v::UnitRange{T}, i::Integer) where T val end +getindex(v::UnitRange{T}, i::Bool) where T = + throw(ArgumentError("invalid index: $i of type Bool")) + const OverflowSafe = Union{Bool,Int8,Int16,Int32,Int64,Int128, UInt8,UInt16,UInt32,UInt64,UInt128} @@ -618,12 +621,18 @@ function getindex(v::UnitRange{T}, i::Integer) where {T<:OverflowSafe} val % T end +getindex(v::UnitRange{T}, i::Bool) where {T<:OverflowSafe} = + throw(ArgumentError("invalid index: $i of type Bool")) + function getindex(v::OneTo{T}, i::Integer) where T @_inline_meta @boundscheck ((i > 0) & (i <= v.stop)) || throw_boundserror(v, i) convert(T, i) end +getindex(v::OneTo{T}, i::Bool) where T = + throw(ArgumentError("invalid index: $i of type Bool")) + function getindex(v::AbstractRange{T}, i::Integer) where T @_inline_meta ret = convert(T, first(v) + (i - 1)*step_hp(v)) @@ -634,12 +643,18 @@ function getindex(v::AbstractRange{T}, i::Integer) where T ret end +getindex(v::AbstractRange{T}, i::Integer) where T = + throw(ArgumentError("invalid index: $i of type Bool")) + function getindex(r::Union{StepRangeLen,LinRange}, i::Integer) @_inline_meta @boundscheck checkbounds(r, i) unsafe_getindex(r, i) end +getindex(r::Union{StepRangeLen,LinRange}, i::Bool) = + throw(ArgumentError("invalid index: $i of type Bool")) + # This is separate to make it useful even when running with --check-bounds=yes function unsafe_getindex(r::StepRangeLen{T}, i::Integer) where T u = i - r.offset @@ -671,12 +686,42 @@ function getindex(r::AbstractUnitRange, s::AbstractUnitRange{<:Integer}) range(st, length=length(s)) end +function getindex(r::AbstractUnitRange, s::AbstractUnitRange{Bool}) + @_inline_meta + @boundscheck checkbounds(r, s) + if length(s) == 0 + return r + elseif length(s) == 1 + if s[1] + return r + else + return range(r[1], length=0) + end + else # length(s) == 2 + return range(r[2], length=1) + end +end + function getindex(r::OneTo{T}, s::OneTo) where T @_inline_meta @boundscheck checkbounds(r, s) OneTo(T(s.stop)) end +function getindex(r::OneTo{T}, s::OneTo{Bool}) where T + @_inline_meta + @boundscheck checkbounds(r, s) + if length(s) == 0 + return r + else # length(s) == 1 + if s[1] + return r + else + return OneTo{T}(zero(T)) + end + end +end + function getindex(r::AbstractUnitRange, s::StepRange{<:Integer}) @_inline_meta @boundscheck checkbounds(r, s) @@ -684,6 +729,22 @@ function getindex(r::AbstractUnitRange, s::StepRange{<:Integer}) range(st, step=step(s), length=length(s)) end +function getindex(r::AbstractUnitRange, s::StepRange{Bool}) + @_inline_meta + @boundscheck checkbounds(r, s) + if length(s) == 0 + return range(r[1], step=one(eltype(r)), length=0) + elseif length(s) == 1 + if s[1] + return range(r[1], step=one(eltype(r)), length=1) + else + return range(r[1], step=one(eltype(r)), length=0) + end + else # length(s) == 2 + return range(r[2], step=one(eltype(r)), length=1) + end +end + function getindex(r::StepRange, s::AbstractRange{<:Integer}) @_inline_meta @boundscheck checkbounds(r, s) @@ -691,6 +752,22 @@ function getindex(r::StepRange, s::AbstractRange{<:Integer}) range(st, step=step(r)*step(s), length=length(s)) end +function getindex(r::StepRange, s::AbstractRange{Bool}) + @_inline_meta + @boundscheck checkbounds(r, s) + if length(s) == 0 + return range(r[1], step=step(r), length=0) + elseif length(s) == 1 + if s[1] + return range(r[1], step=step(r), length=1) + else + return range(r[1], step=step(r), length=0) + end + else # length(s) == 2 + return range(r[2], step=step(r), length=1) + end +end + function getindex(r::StepRangeLen{T}, s::OrdinalRange{<:Integer}) where {T} @_inline_meta @boundscheck checkbounds(r, s) @@ -701,6 +778,23 @@ function getindex(r::StepRangeLen{T}, s::OrdinalRange{<:Integer}) where {T} return StepRangeLen{T}(ref, r.step*step(s), length(s), offset) end +function getindex(r::StepRangeLen{T}, s::OrdinalRange{Bool}) where {T} + @_inline_meta + @boundscheck checkbounds(r, s) + + if length(s) == 0 + return StepRangeLen{T}(r[1], step(r), 0, 1) + elseif length(s) == 1 + if s[1] + return StepRangeLen{T}(r[1], step(r), 1, 1) + else + return StepRangeLen{T}(r[1], step(r), 0, 1) + end + else # length(s) == 2 + return StepRangeLen{T}(r[2], step(r), 1, 1) + end +end + function getindex(r::LinRange, s::OrdinalRange{<:Integer}) @_inline_meta @boundscheck checkbounds(r, s) @@ -709,6 +803,23 @@ function getindex(r::LinRange, s::OrdinalRange{<:Integer}) return LinRange(vfirst, vlast, length(s)) end +function getindex(r::LinRange, s::OrdinalRange{Bool}) + @_inline_meta + @boundscheck checkbounds(r, s) + + if length(s) == 0 + return LinRange(r[1], r[1], 0) + elseif length(s) == 1 + if s[1] + return LinRange(r[1], r[1], 1) + else + return LinRange(r[1], r[1], 0) + end + else # length(s) == 2 + return LinRange(r[2], r[2], 1) + end +end + show(io::IO, r::AbstractRange) = print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") From 1cdfe4d27bb5fd318d79bd8bb22f11b81d9588d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 15:42:49 +0100 Subject: [PATCH 02/22] Update base/range.jl Co-authored-by: Matt Bauman --- base/range.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/range.jl b/base/range.jl index 7b4fa0b03047e..02a05b658e9eb 100644 --- a/base/range.jl +++ b/base/range.jl @@ -643,7 +643,7 @@ function getindex(v::AbstractRange{T}, i::Integer) where T ret end -getindex(v::AbstractRange{T}, i::Integer) where T = +getindex(v::AbstractRange{T}, i::Bool) where T = throw(ArgumentError("invalid index: $i of type Bool")) function getindex(r::Union{StepRangeLen,LinRange}, i::Integer) From 759e1c0801d3fda545e4a1cc9ba0de97d11b50f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 21:43:19 +0100 Subject: [PATCH 03/22] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 7793ba31b7f24..2d0fcf04a330a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,7 @@ New language features Language changes ---------------- +* ranges now correctly handle `Bool` indexing ([#31829]) Compiler/Runtime improvements ----------------------------- From 04aa80d0c92fc488e57e1efaef5fea991c714a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 22:05:12 +0100 Subject: [PATCH 04/22] Update base/range.jl --- base/range.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/base/range.jl b/base/range.jl index 5b3934ca1616a..25c19fcad6808 100644 --- a/base/range.jl +++ b/base/range.jl @@ -793,10 +793,7 @@ function getindex(r::OneTo{T}, s::OneTo{Bool}) where T if length(s) == 0 return r else # length(s) == 1 - if s[1] - return r - else - return OneTo{T}(zero(T)) + return r end end end From 23ffd5204317cfe49a439cfb4d05de2cbce2d6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 22:06:21 +0100 Subject: [PATCH 05/22] Update base/range.jl --- base/range.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/base/range.jl b/base/range.jl index 25c19fcad6808..cd22699d94e43 100644 --- a/base/range.jl +++ b/base/range.jl @@ -790,12 +790,7 @@ end function getindex(r::OneTo{T}, s::OneTo{Bool}) where T @_inline_meta @boundscheck checkbounds(r, s) - if length(s) == 0 - return r - else # length(s) == 1 - return r - end - end + return r end function getindex(r::AbstractUnitRange, s::StepRange{<:Integer}) From f6ec9843f3b387d2607c0c128306a73d5929c2c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 22:23:37 +0100 Subject: [PATCH 06/22] Update ranges.jl --- test/ranges.jl | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/test/ranges.jl b/test/ranges.jl index 6fcfc18b50529..6bc8e7fa57520 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1730,3 +1730,122 @@ end @test eltype(StepRangeLen(Int8(1), Int8(2), 3, 2)) === Int8 @test typeof(step(StepRangeLen(Int8(1), Int8(2), 3, 2))) === Int8 end + +@testset "Bool indexing of ranges" begin + @test_throws ArgumentError (1:2)[true] + @test_throws ArgumentError (big(1):big(2))[true] + @test_throws ArgumentError Base.OneTo(10)[true] + @test_throws ArgumentError (1:2:5)[true] + @test_throws ArgumentError LinRange(1,2,2)[true] + @test_throws ArgumentError (1.0:2.0:5.0)[true] + + r = 3:2 + r2 = r[true:flase] + @test r.start == r2.start && r.stop == r2.stop + @test_throws BoundsError r[true:true] + @test_throws BoundsError r[false:true] + + r = 3:3 + r2 = r[true:true] + @test r.start == r2.start && r.stop == r2.stop + r2 = r[false:false] + @test r2.start == 3 && r2.stop == 2 + @test_throws BoundsError r[true:false] + @test_throws BoundsError r[false:true] + + r = 2:3 + r2 = r[false:true] + @test r2.start == r2.stop == 3 + @test_throws BoundsError r[true:false] + @test_throws BoundsError r[true:true] + + r = Base.OneTo(0) + r2 = r[Base.OneTo(false)] + @test r2 isa Base.OneTo && r2.stop == 0 + @test_throws BoundsError r[Base.OneTo(true)] + + r = Base.OneTo(1) + r2 = r[Base.OneTo(true)] + @test r2 isa Base.OneTo && r2.stop == 1 + @test_throws BoundsError r[Base.OneTo(false)] + + @test_throws BoundsError Base.OneTo(2)[Base.OneTo(false)] + @test_throws BoundsError Base.OneTo(2)[Base.OneTo(true)] + + r = 2:1 + r2 = r[true:true:false] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 + @test_throws BoundsError r[false:true:false] + + r = 2:2 + r2 = r[false:true:false] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 + r2 = r[true:true:true] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[false:true:true] + + r = 1:2 + r2 = r[false:true:true] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[true:true:true] + + r = 2:1:1 + r2 = r[true:true:false] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 + @test_throws BoundsError r[false:true:false] + + r = 2:1:2 + r2 = r[false:true:false] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 + r2 = r[true:true:true] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[false:true:true] + + r = 1:1:2 + r2 = r[false:true:true] + @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[true:true:true] + + r = 2.0:1.0:1.0 + r2 = r[true:true:false] + @test r2 isa StepRangeLen && r2 == 2:1 + @test_throws BoundsError r[false:true:false] + + r = 2.0:1.0:2.0 + r2 = r[false:true:false] + @test r2 isa StepRangeLen && r2 == 2:1 + r2 = r[true:true:true] + @test r2 isa StepRangeLen && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[false:true:true] + + r = 1.0:1.0:2.0 + r2 = r[false:true:true] + @test r2 isa StepRangeLen && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[true:true:true] + + r = LinRange(2, 1, 0) + r2 = r[true:true:false] + @test r2 isa LinRange && r2 == 2:1 + @test_throws BoundsError r[false:true:false] + + r = LinRange(2, 2, 1) + r2 = r[false:true:false] + @test r2 isa LinRange && r2 == 2:1 + r2 = r[true:true:true] + @test r2 isa LinRange && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[false:true:true] + + r = LinRange(1, 2, 1) + r2 = r[false:true:true] + @test r2 isa LinRange && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[true:true:true] + +end From 1047017670eae2f0ba6af4f930ae51ab65d0a425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 6 Jan 2021 22:24:03 +0100 Subject: [PATCH 07/22] Update test/ranges.jl --- test/ranges.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/ranges.jl b/test/ranges.jl index 6bc8e7fa57520..f0693335f83c3 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1847,5 +1847,4 @@ end @test r2 isa LinRange && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] - end From 6ad94ded29bdbb298002442dca1a84a3eef2a8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 7 Jan 2021 19:19:25 +0100 Subject: [PATCH 08/22] Apply suggestions from code review Co-authored-by: Matt Bauman --- NEWS.md | 2 +- test/ranges.jl | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2d0fcf04a330a..53c5c65e01d01 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,7 +7,7 @@ New language features Language changes ---------------- -* ranges now correctly handle `Bool` indexing ([#31829]) +* Subtypes of `AbstractRange` now correctly follow the general array indexing behavior when indexed by `Bool`s, erroring for scalar `Bool`s and treating arrays (including ranges) of `Bool` as an logical index ([#31829]) Compiler/Runtime improvements ----------------------------- diff --git a/test/ranges.jl b/test/ranges.jl index f0693335f83c3..106e65acc2ea6 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1738,13 +1738,11 @@ end @test_throws ArgumentError (1:2:5)[true] @test_throws ArgumentError LinRange(1,2,2)[true] @test_throws ArgumentError (1.0:2.0:5.0)[true] - r = 3:2 - r2 = r[true:flase] + r2 = r[true:false] @test r.start == r2.start && r.stop == r2.stop @test_throws BoundsError r[true:true] @test_throws BoundsError r[false:true] - r = 3:3 r2 = r[true:true] @test r.start == r2.start && r.stop == r2.stop @@ -1752,13 +1750,11 @@ end @test r2.start == 3 && r2.stop == 2 @test_throws BoundsError r[true:false] @test_throws BoundsError r[false:true] - r = 2:3 r2 = r[false:true] @test r2.start == r2.stop == 3 @test_throws BoundsError r[true:false] @test_throws BoundsError r[true:true] - r = Base.OneTo(0) r2 = r[Base.OneTo(false)] @test r2 isa Base.OneTo && r2.stop == 0 @@ -1771,7 +1767,6 @@ end @test_throws BoundsError Base.OneTo(2)[Base.OneTo(false)] @test_throws BoundsError Base.OneTo(2)[Base.OneTo(true)] - r = 2:1 r2 = r[true:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 From 39b54195ff329c64fa39eeb076e132a00839cbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 7 Jan 2021 19:20:24 +0100 Subject: [PATCH 09/22] Update NEWS.md --- NEWS.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 53c5c65e01d01..da179b8f502ab 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,7 +7,9 @@ New language features Language changes ---------------- -* Subtypes of `AbstractRange` now correctly follow the general array indexing behavior when indexed by `Bool`s, erroring for scalar `Bool`s and treating arrays (including ranges) of `Bool` as an logical index ([#31829]) +* Subtypes of `AbstractRange` now correctly follow the general array indexing + behavior when indexed by `Bool`s, erroring for scalar `Bool`s and treating + arrays (including ranges) of `Bool` as an logical index ([#31829]) Compiler/Runtime improvements ----------------------------- From 8a10ef79779ce6a4803ed55b755d2584fc85a443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 7 Jan 2021 20:07:42 +0100 Subject: [PATCH 10/22] Update NEWS.md --- NEWS.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index da179b8f502ab..9abe14230128c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,12 +4,10 @@ Julia v1.7 Release Notes New language features --------------------- + Language changes ---------------- -* Subtypes of `AbstractRange` now correctly follow the general array indexing - behavior when indexed by `Bool`s, erroring for scalar `Bool`s and treating - arrays (including ranges) of `Bool` as an logical index ([#31829]) Compiler/Runtime improvements ----------------------------- @@ -47,6 +45,9 @@ Standard library changes * `iseven` and `isodd` functions now support non-`Integer` numeric types ([#38976]). * `escape_string` can now receive a collection of characters in the keyword `keep` that are to be kept as they are. ([#38597]). +* Subtypes of `AbstractRange` now correctly follow the general array indexing + behavior when indexed by `Bool`s, erroring for scalar `Bool`s and treating + arrays (including ranges) of `Bool` as an logical index ([#31829]) #### Package Manager From bd4421133da77c8e2376a8cb30e9710ddcd0d86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 11:45:44 +0100 Subject: [PATCH 11/22] do not introduce new methods --- NEWS.md | 1 - base/range.jl | 198 ++++++++++++++++++----------------------- base/twiceprecision.jl | 40 ++++++--- test/ranges.jl | 21 ++++- 4 files changed, 137 insertions(+), 123 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9abe14230128c..50cf2a44672f3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,6 @@ Julia v1.7 Release Notes New language features --------------------- - Language changes ---------------- diff --git a/base/range.jl b/base/range.jl index cd22699d94e43..bdd39f5a3f6d7 100644 --- a/base/range.jl +++ b/base/range.jl @@ -682,38 +682,33 @@ _in_unit_range(v::UnitRange, val, i::Integer) = i > 0 && val <= v.stop && val >= function getindex(v::UnitRange{T}, i::Integer) where T @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) val = convert(T, v.start + (i - 1)) @boundscheck _in_unit_range(v, val, i) || throw_boundserror(v, i) val end -getindex(v::UnitRange{T}, i::Bool) where T = - throw(ArgumentError("invalid index: $i of type Bool")) - const OverflowSafe = Union{Bool,Int8,Int16,Int32,Int64,Int128, UInt8,UInt16,UInt32,UInt64,UInt128} function getindex(v::UnitRange{T}, i::Integer) where {T<:OverflowSafe} @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) val = v.start + (i - 1) @boundscheck _in_unit_range(v, val, i) || throw_boundserror(v, i) val % T end -getindex(v::UnitRange{T}, i::Bool) where {T<:OverflowSafe} = - throw(ArgumentError("invalid index: $i of type Bool")) - function getindex(v::OneTo{T}, i::Integer) where T @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) @boundscheck ((i > 0) & (i <= v.stop)) || throw_boundserror(v, i) convert(T, i) end -getindex(v::OneTo{T}, i::Bool) where T = - throw(ArgumentError("invalid index: $i of type Bool")) - function getindex(v::AbstractRange{T}, i::Integer) where T @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) ret = convert(T, first(v) + (i - 1)*step_hp(v)) ok = ifelse(step(v) > zero(step(v)), (ret <= last(v)) & (ret >= first(v)), @@ -722,30 +717,28 @@ function getindex(v::AbstractRange{T}, i::Integer) where T ret end -getindex(v::AbstractRange{T}, i::Bool) where T = - throw(ArgumentError("invalid index: $i of type Bool")) - function getindex(r::Union{StepRangeLen,LinRange}, i::Integer) @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) @boundscheck checkbounds(r, i) unsafe_getindex(r, i) end -getindex(r::Union{StepRangeLen,LinRange}, i::Bool) = - throw(ArgumentError("invalid index: $i of type Bool")) - # This is separate to make it useful even when running with --check-bounds=yes function unsafe_getindex(r::StepRangeLen{T}, i::Integer) where T + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) u = i - r.offset T(r.ref + u*r.step) end function _getindex_hiprec(r::StepRangeLen, i::Integer) # without rounding by T + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) u = i - r.offset r.ref + u*r.step end function unsafe_getindex(r::LinRange, i::Integer) + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) lerpi(i-1, r.lendiv, r.start, r.stop) end @@ -757,137 +750,124 @@ end getindex(r::AbstractRange, ::Colon) = copy(r) -function getindex(r::AbstractUnitRange, s::AbstractUnitRange{<:Integer}) +function getindex(r::AbstractUnitRange, s::AbstractUnitRange{T}) where {T<:Integer} @_inline_meta @boundscheck checkbounds(r, s) - f = first(r) - st = oftype(f, f + first(s)-1) - range(st, length=length(s)) -end -function getindex(r::AbstractUnitRange, s::AbstractUnitRange{Bool}) - @_inline_meta - @boundscheck checkbounds(r, s) - if length(s) == 0 - return r - elseif length(s) == 1 - if s[1] + if T === Bool + if length(s) == 0 return r - else - return range(r[1], length=0) + elseif length(s) == 1 + if first(s) + return r + else + return range(r[1], length=0) + end + else # length(s) == 2 + return range(r[2], length=1) end - else # length(s) == 2 - return range(r[2], length=1) + else + f = first(r) + st = oftype(f, f + first(s)-1) + return range(st, length=length(s)) end end -function getindex(r::OneTo{T}, s::OneTo) where T +function getindex(r::OneTo{T}, s::OneTo{S}) where {T, S} @_inline_meta @boundscheck checkbounds(r, s) - OneTo(T(s.stop)) + S === Bool ? r : OneTo(T(s.stop)) end -function getindex(r::OneTo{T}, s::OneTo{Bool}) where T +function getindex(r::AbstractUnitRange, s::StepRange{T}) where {T<:Integer} @_inline_meta @boundscheck checkbounds(r, s) - return r -end - -function getindex(r::AbstractUnitRange, s::StepRange{<:Integer}) - @_inline_meta - @boundscheck checkbounds(r, s) - st = oftype(first(r), first(r) + s.start-1) - range(st, step=step(s), length=length(s)) -end -function getindex(r::AbstractUnitRange, s::StepRange{Bool}) - @_inline_meta - @boundscheck checkbounds(r, s) - if length(s) == 0 - return range(r[1], step=one(eltype(r)), length=0) - elseif length(s) == 1 - if s[1] - return range(r[1], step=one(eltype(r)), length=1) - else - return range(r[1], step=one(eltype(r)), length=0) + if T === Bool + if length(s) == 0 + return range(first(r), step=one(eltype(r)), length=0) + elseif length(s) == 1 + if first(s) + return range(first(r), step=one(eltype(r)), length=1) + else + return range(first(r), step=one(eltype(r)), length=0) + end + else # length(s) == 2 + return range(r[2], step=one(eltype(r)), length=1) end - else # length(s) == 2 - return range(r[2], step=one(eltype(r)), length=1) + else + st = oftype(first(r), first(r) + s.start-1) + return range(st, step=step(s), length=length(s)) end end -function getindex(r::StepRange, s::AbstractRange{<:Integer}) +function getindex(r::StepRange, s::AbstractRange{T}) where {T<:Integer} @_inline_meta @boundscheck checkbounds(r, s) - st = oftype(r.start, r.start + (first(s)-1)*step(r)) - range(st, step=step(r)*step(s), length=length(s)) -end -function getindex(r::StepRange, s::AbstractRange{Bool}) - @_inline_meta - @boundscheck checkbounds(r, s) - if length(s) == 0 - return range(r[1], step=step(r), length=0) - elseif length(s) == 1 - if s[1] - return range(r[1], step=step(r), length=1) - else - return range(r[1], step=step(r), length=0) + if T === Bool + if length(s) == 0 + return range(first(r), step=step(r), length=0) + elseif length(s) == 1 + if first(s) + return range(first(r), step=step(r), length=1) + else + return range(first(r), step=step(r), length=0) + end + else # length(s) == 2 + return range(r[2], step=step(r), length=1) end - else # length(s) == 2 - return range(r[2], step=step(r), length=1) + else + st = oftype(r.start, r.start + (first(s)-1)*step(r)) + return range(st, step=step(r)*step(s), length=length(s)) end end -function getindex(r::StepRangeLen{T}, s::OrdinalRange{<:Integer}) where {T} - @_inline_meta - @boundscheck checkbounds(r, s) - # Find closest approach to offset by s - ind = LinearIndices(s) - offset = max(min(1 + round(Int, (r.offset - first(s))/step(s)), last(ind)), first(ind)) - ref = _getindex_hiprec(r, first(s) + (offset-1)*step(s)) - return StepRangeLen{T}(ref, r.step*step(s), length(s), offset) -end - -function getindex(r::StepRangeLen{T}, s::OrdinalRange{Bool}) where {T} +function getindex(r::StepRangeLen{T}, s::OrdinalRange{S}) where {T, S<:Integer} @_inline_meta @boundscheck checkbounds(r, s) - if length(s) == 0 - return StepRangeLen{T}(r[1], step(r), 0, 1) - elseif length(s) == 1 - if s[1] - return StepRangeLen{T}(r[1], step(r), 1, 1) - else - return StepRangeLen{T}(r[1], step(r), 0, 1) + if S === Bool + if length(s) == 0 + return StepRangeLen{T}(first(r), step(r), 0, 1) + elseif length(s) == 1 + if first(s) + return StepRangeLen{T}(first(r), step(r), 1, 1) + else + return StepRangeLen{T}(first(r), step(r), 0, 1) + end + else # length(s) == 2 + return StepRangeLen{T}(r[2], step(r), 1, 1) end - else # length(s) == 2 - return StepRangeLen{T}(r[2], step(r), 1, 1) + else + # Find closest approach to offset by s + ind = LinearIndices(s) + offset = max(min(1 + round(Int, (r.offset - first(s))/step(s)), last(ind)), first(ind)) + ref = _getindex_hiprec(r, first(s) + (offset-1)*step(s)) + return StepRangeLen{T}(ref, r.step*step(s), length(s), offset) end end -function getindex(r::LinRange{T}, s::OrdinalRange{<:Integer}) where {T} +function getindex(r::LinRange{T}, s::OrdinalRange{S}) where {T, S<:Integer} @_inline_meta @boundscheck checkbounds(r, s) - vfirst = unsafe_getindex(r, first(s)) - vlast = unsafe_getindex(r, last(s)) - return LinRange{T}(vfirst, vlast, length(s)) -end -function getindex(r::LinRange, s::OrdinalRange{Bool}) - @_inline_meta - @boundscheck checkbounds(r, s) - - if length(s) == 0 - return LinRange(r[1], r[1], 0) - elseif length(s) == 1 - if s[1] - return LinRange(r[1], r[1], 1) - else - return LinRange(r[1], r[1], 0) + if S === Bool + if length(s) == 0 + return LinRange(first(r), first(r), 0) + elseif length(s) == 1 + if first(s) + return LinRange(first(r), first(r), 1) + else + return LinRange(first(r), first(r), 0) + end + else # length(s) == 2 + return LinRange(r[2], r[2], 1) end - else # length(s) == 2 - return LinRange(r[2], r[2], 1) + else + vfirst = unsafe_getindex(r, first(s)) + vlast = unsafe_getindex(r, last(s)) + return LinRange{T}(vfirst, vlast, length(s)) end end diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 1490a0624c7d6..48e39150e887b 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -448,6 +448,7 @@ end function unsafe_getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, i::Integer) where T # Very similar to _getindex_hiprec, but optimized to avoid a 2nd call to add12 @_inline_meta + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) u = i - r.offset shift_hi, shift_lo = u*r.step.hi, u*r.step.lo x_hi, x_lo = add12(r.ref.hi, shift_hi) @@ -455,6 +456,7 @@ function unsafe_getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, i end function _getindex_hiprec(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecision}, i::Integer) + i isa Bool && throw(ArgumentError("invalid index: $i of type Bool")) u = i - r.offset shift_hi, shift_lo = u*r.step.hi, u*r.step.lo x_hi, x_lo = add12(r.ref.hi, shift_hi) @@ -462,20 +464,34 @@ function _getindex_hiprec(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecisio TwicePrecision(x_hi, x_lo) end -function getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, s::OrdinalRange{<:Integer}) where T +function getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, s::OrdinalRange{S}) where {T, S<:Integer} @boundscheck checkbounds(r, s) - soffset = 1 + round(Int, (r.offset - first(s))/step(s)) - soffset = clamp(soffset, 1, length(s)) - ioffset = first(s) + (soffset-1)*step(s) - if step(s) == 1 || length(s) < 2 - newstep = r.step - else - newstep = twiceprecision(r.step*step(s), nbitslen(T, length(s), soffset)) - end - if ioffset == r.offset - StepRangeLen(r.ref, newstep, length(s), max(1,soffset)) + if S === Bool + if length(s) == 0 + return StepRangeLen(r.ref, r.step, 0, 1) + elseif length(s) == 1 + if first(s) + return StepRangeLen(r.ref, r.step, 1, 1) + else + return StepRangeLen(r.ref, r.step, 0, 1) + end + else # length(s) == 2 + return StepRangeLen(r[2], step(r), 1, 1) + end else - StepRangeLen(r.ref + (ioffset-r.offset)*r.step, newstep, length(s), max(1,soffset)) + soffset = 1 + round(Int, (r.offset - first(s))/step(s)) + soffset = clamp(soffset, 1, length(s)) + ioffset = first(s) + (soffset-1)*step(s) + if step(s) == 1 || length(s) < 2 + newstep = r.step + else + newstep = twiceprecision(r.step*step(s), nbitslen(T, length(s), soffset)) + end + if ioffset == r.offset + return StepRangeLen(r.ref, newstep, length(s), max(1,soffset)) + else + return StepRangeLen(r.ref + (ioffset-r.offset)*r.step, newstep, length(s), max(1,soffset)) + end end end diff --git a/test/ranges.jl b/test/ranges.jl index 106e65acc2ea6..ac55478698d96 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1824,6 +1824,25 @@ end @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] + r = StepRangeLen(2, 1, 0) + r2 = r[true:true:false] + @test r2 isa StepRangeLen && r2 == 2:1 + @test_throws BoundsError r[false:true:false] + + r = StepRangeLen(2, 1, 1) + r2 = r[false:true:false] + @test r2 isa StepRangeLen && r2 == 2:1 + r2 = r[true:true:true] + @test r2 isa StepRangeLen && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[false:true:true] + + r = StepRangeLen(1, 1, 2) + r2 = r[false:true:true] + @test r2 isa StepRangeLen && r2 == 2:2 + @test_throws BoundsError r[true:true:false] + @test_throws BoundsError r[true:true:true] + r = LinRange(2, 1, 0) r2 = r[true:true:false] @test r2 isa LinRange && r2 == 2:1 @@ -1837,7 +1856,7 @@ end @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] - r = LinRange(1, 2, 1) + r = LinRange(1, 2, 2) r2 = r[false:true:true] @test r2 isa LinRange && r2 == 2:2 @test_throws BoundsError r[true:true:false] From b67c55cba5929b258def03b64e7b48d1d390ffbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 13:35:47 +0100 Subject: [PATCH 12/22] try to identify source of the problem with views --- test/ranges.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/ranges.jl b/test/ranges.jl index ac55478698d96..88020e981a812 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1456,6 +1456,12 @@ end tt = Base.tuple_type_tail(m.sig) tt == Tuple{AbstractArray,Vararg{Any,N}} where N && continue vm = findfirst(sig->tt <: Base.tuple_type_tail(sig.sig), vmt) + if vmt[vm].sig == Tuple{typeof(view),AbstractArray,Vararg{Any,N}} where N + @show vm + @show vmt[vm] + @show sig + @show vmt[vm].sig + end @test vmt[vm].sig != Tuple{typeof(view),AbstractArray,Vararg{Any,N}} where N end end From 3391dc78446e92f03644f43feda85d80f9fbb33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 16:53:10 +0100 Subject: [PATCH 13/22] Disallow OneTo(::Bool) --- base/range.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/range.jl b/base/range.jl index bdd39f5a3f6d7..0ef15d6568bf7 100644 --- a/base/range.jl +++ b/base/range.jl @@ -327,8 +327,10 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} function OneTo{T}(r::AbstractRange) where {T<:Integer} throwstart(r) = (@_noinline_meta; throw(ArgumentError("first element must be 1, got $(first(r))"))) throwstep(r) = (@_noinline_meta; throw(ArgumentError("step must be 1, got $(step(r))"))) + throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) first(r) == 1 || throwstart(r) step(r) == 1 || throwstep(r) + r isa Bool && throwbool(r) return new(max(zero(T), last(r))) end end @@ -773,10 +775,10 @@ function getindex(r::AbstractUnitRange, s::AbstractUnitRange{T}) where {T<:Integ end end -function getindex(r::OneTo{T}, s::OneTo{S}) where {T, S} +function getindex(r::OneTo{T}, s::OneTo) where T @_inline_meta @boundscheck checkbounds(r, s) - S === Bool ? r : OneTo(T(s.stop)) + OneTo(T(s.stop)) end function getindex(r::AbstractUnitRange, s::StepRange{T}) where {T<:Integer} From 427beb49609f1149db114e872e26670baed2dec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 16:53:34 +0100 Subject: [PATCH 14/22] Update test/ranges.jl --- test/ranges.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/ranges.jl b/test/ranges.jl index 88020e981a812..ac55478698d96 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1456,12 +1456,6 @@ end tt = Base.tuple_type_tail(m.sig) tt == Tuple{AbstractArray,Vararg{Any,N}} where N && continue vm = findfirst(sig->tt <: Base.tuple_type_tail(sig.sig), vmt) - if vmt[vm].sig == Tuple{typeof(view),AbstractArray,Vararg{Any,N}} where N - @show vm - @show vmt[vm] - @show sig - @show vmt[vm].sig - end @test vmt[vm].sig != Tuple{typeof(view),AbstractArray,Vararg{Any,N}} where N end end From 6aafb09aa506ca743f482afd59a16bd519b46613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 16:54:39 +0100 Subject: [PATCH 15/22] Update test/ranges.jl --- test/ranges.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/ranges.jl b/test/ranges.jl index ac55478698d96..b409192134653 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1760,13 +1760,6 @@ end @test r2 isa Base.OneTo && r2.stop == 0 @test_throws BoundsError r[Base.OneTo(true)] - r = Base.OneTo(1) - r2 = r[Base.OneTo(true)] - @test r2 isa Base.OneTo && r2.stop == 1 - @test_throws BoundsError r[Base.OneTo(false)] - - @test_throws BoundsError Base.OneTo(2)[Base.OneTo(false)] - @test_throws BoundsError Base.OneTo(2)[Base.OneTo(true)] r = 2:1 r2 = r[true:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 From c40212cb4a1c8b5f52383d5cb4a3312e4d07e66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 16:55:24 +0100 Subject: [PATCH 16/22] Update test/ranges.jl --- test/ranges.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/ranges.jl b/test/ranges.jl index b409192134653..a36b76d9bbc72 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1755,10 +1755,6 @@ end @test r2.start == r2.stop == 3 @test_throws BoundsError r[true:false] @test_throws BoundsError r[true:true] - r = Base.OneTo(0) - r2 = r[Base.OneTo(false)] - @test r2 isa Base.OneTo && r2.stop == 0 - @test_throws BoundsError r[Base.OneTo(true)] r = 2:1 r2 = r[true:true:false] From e23cede311cd7f4d96a5315445dad89f6f1313da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 17:01:31 +0100 Subject: [PATCH 17/22] Update test/ranges.jl --- test/ranges.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ranges.jl b/test/ranges.jl index a36b76d9bbc72..2364f4bcbd9e7 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1732,6 +1732,8 @@ end end @testset "Bool indexing of ranges" begin + @test_throws ArgumentError Base.OneTo(true) + @test_throws ArgumentError (1:2)[true] @test_throws ArgumentError (big(1):big(2))[true] @test_throws ArgumentError Base.OneTo(10)[true] From aebe5f3586b999d170595857567382fe64f78d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 19:41:39 +0100 Subject: [PATCH 18/22] Fix OneTo --- base/range.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/base/range.jl b/base/range.jl index 0ef15d6568bf7..3536b7d654d4d 100644 --- a/base/range.jl +++ b/base/range.jl @@ -323,14 +323,18 @@ be 1. """ struct OneTo{T<:Integer} <: AbstractUnitRange{T} stop::T - OneTo{T}(stop) where {T<:Integer} = new(max(zero(T), stop)) + function OneTo{T}(stop) where {T<:Integer} + throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) + T isa Bool && throwbool(r) + return new(max(zero(T), stop)) + return function OneTo{T}(r::AbstractRange) where {T<:Integer} throwstart(r) = (@_noinline_meta; throw(ArgumentError("first element must be 1, got $(first(r))"))) throwstep(r) = (@_noinline_meta; throw(ArgumentError("step must be 1, got $(step(r))"))) throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) first(r) == 1 || throwstart(r) step(r) == 1 || throwstep(r) - r isa Bool && throwbool(r) + T isa Bool && throwbool(r) return new(max(zero(T), last(r))) end end From 2ae87109bc5ac2806c65835919feff774cdd7385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 19:42:13 +0100 Subject: [PATCH 19/22] Update base/range.jl --- base/range.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/range.jl b/base/range.jl index 3536b7d654d4d..151430ffa801b 100644 --- a/base/range.jl +++ b/base/range.jl @@ -327,7 +327,8 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) T isa Bool && throwbool(r) return new(max(zero(T), stop)) - return + end + function OneTo{T}(r::AbstractRange) where {T<:Integer} throwstart(r) = (@_noinline_meta; throw(ArgumentError("first element must be 1, got $(first(r))"))) throwstep(r) = (@_noinline_meta; throw(ArgumentError("step must be 1, got $(step(r))"))) From 55f24874d1506871c450be541dcaf17e8f8fe341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 21:59:47 +0100 Subject: [PATCH 20/22] Apply suggestions from code review --- base/range.jl | 4 ++-- test/ranges.jl | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/base/range.jl b/base/range.jl index 151430ffa801b..2708e6c864e43 100644 --- a/base/range.jl +++ b/base/range.jl @@ -325,7 +325,7 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} stop::T function OneTo{T}(stop) where {T<:Integer} throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) - T isa Bool && throwbool(r) + T === Bool && throwbool(r) return new(max(zero(T), stop)) end @@ -335,7 +335,7 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) first(r) == 1 || throwstart(r) step(r) == 1 || throwstep(r) - T isa Bool && throwbool(r) + T === Bool && throwbool(r) return new(max(zero(T), last(r))) end end diff --git a/test/ranges.jl b/test/ranges.jl index 2364f4bcbd9e7..ffb69838f69b5 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1733,6 +1733,7 @@ end @testset "Bool indexing of ranges" begin @test_throws ArgumentError Base.OneTo(true) + @test_throws ArgumentError Base.OneTo(true:true:true) @test_throws ArgumentError (1:2)[true] @test_throws ArgumentError (big(1):big(2))[true] From 447caa7ebba59d9c59d29f59da45065bb7ca6823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 12 Jan 2021 23:42:48 +0100 Subject: [PATCH 21/22] Update base/range.jl --- base/range.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/range.jl b/base/range.jl index 2708e6c864e43..6095b710a5ef3 100644 --- a/base/range.jl +++ b/base/range.jl @@ -325,7 +325,7 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} stop::T function OneTo{T}(stop) where {T<:Integer} throwbool(r) = (@_noinline_meta; throw(ArgumentError("invalid index: $r of type Bool"))) - T === Bool && throwbool(r) + T === Bool && throwbool(stop) return new(max(zero(T), stop)) end From 8e7143434371d6efb4f00aceabba9bc0500ffc2e Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 25 Jan 2021 10:25:23 -0500 Subject: [PATCH 22/22] add tests comparing to Array behaviors --- test/ranges.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/ranges.jl b/test/ranges.jl index f28352e60d50f..4af3cb2964599 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1767,11 +1767,13 @@ end @test_throws ArgumentError (1.0:2.0:5.0)[true] r = 3:2 r2 = r[true:false] + @test r2 == collect(r)[true:false] @test r.start == r2.start && r.stop == r2.stop @test_throws BoundsError r[true:true] @test_throws BoundsError r[false:true] r = 3:3 r2 = r[true:true] + @test r2 == collect(r)[true:true] @test r.start == r2.start && r.stop == r2.stop r2 = r[false:false] @test r2.start == 3 && r2.stop == 2 @@ -1779,101 +1781,122 @@ end @test_throws BoundsError r[false:true] r = 2:3 r2 = r[false:true] + @test r2 == collect(r)[false:true] @test r2.start == r2.stop == 3 @test_throws BoundsError r[true:false] @test_throws BoundsError r[true:true] r = 2:1 r2 = r[true:true:false] + @test r2 == collect(r)[true:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 @test_throws BoundsError r[false:true:false] r = 2:2 r2 = r[false:true:false] + @test r2 == collect(r)[false:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 r2 = r[true:true:true] + @test r2 == collect(r)[true:true:true] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] r = 1:2 r2 = r[false:true:true] + @test r2 == collect(r)[false:true:true] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] r = 2:1:1 r2 = r[true:true:false] + @test r2 == collect(r)[true:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 @test_throws BoundsError r[false:true:false] r = 2:1:2 r2 = r[false:true:false] + @test r2 == collect(r)[false:true:false] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 1 r2 = r[true:true:true] + @test r2 == collect(r)[true:true:true] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] r = 1:1:2 r2 = r[false:true:true] + @test r2 == collect(r)[false:true:true] @test r2 isa StepRange && r2.start == 2 && r2.step == 1 && r2.stop == 2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] r = 2.0:1.0:1.0 r2 = r[true:true:false] + @test r2 == collect(r)[true:true:false] @test r2 isa StepRangeLen && r2 == 2:1 @test_throws BoundsError r[false:true:false] r = 2.0:1.0:2.0 r2 = r[false:true:false] + @test r2 == collect(r)[false:true:false] @test r2 isa StepRangeLen && r2 == 2:1 r2 = r[true:true:true] + @test r2 == collect(r)[true:true:true] @test r2 isa StepRangeLen && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] r = 1.0:1.0:2.0 r2 = r[false:true:true] + @test r2 == collect(r)[false:true:true] @test r2 isa StepRangeLen && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] r = StepRangeLen(2, 1, 0) r2 = r[true:true:false] + @test r2 == collect(r)[true:true:false] @test r2 isa StepRangeLen && r2 == 2:1 @test_throws BoundsError r[false:true:false] r = StepRangeLen(2, 1, 1) r2 = r[false:true:false] + @test r2 == collect(r)[false:true:false] @test r2 isa StepRangeLen && r2 == 2:1 r2 = r[true:true:true] + @test r2 == collect(r)[true:true:true] @test r2 isa StepRangeLen && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] r = StepRangeLen(1, 1, 2) r2 = r[false:true:true] + @test r2 == collect(r)[false:true:true] @test r2 isa StepRangeLen && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] r = LinRange(2, 1, 0) r2 = r[true:true:false] + @test r2 == collect(r)[true:true:false] @test r2 isa LinRange && r2 == 2:1 @test_throws BoundsError r[false:true:false] r = LinRange(2, 2, 1) r2 = r[false:true:false] + @test r2 == collect(r)[false:true:false] @test r2 isa LinRange && r2 == 2:1 r2 = r[true:true:true] + @test r2 == collect(r)[true:true:true] @test r2 isa LinRange && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[false:true:true] r = LinRange(1, 2, 2) r2 = r[false:true:true] + @test r2 == collect(r)[false:true:true] @test r2 isa LinRange && r2 == 2:2 @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true]