diff --git a/NEWS.md b/NEWS.md index 59399f42c64f1..4603afa4ad037 100644 --- a/NEWS.md +++ b/NEWS.md @@ -153,6 +153,7 @@ New library features Standard library changes ------------------------ +* Empty ranges now compare equal, regardless of their startpoint and step ([#32348]). * A 1-d `Zip` iterator (where `Base.IteratorSize` is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error with truncated iterators) ([#29927]). * The `@timed` macro now returns a `NamedTuple` ([#34149]) * New `supertypes(T)` function returns a tuple of all supertypes of `T` ([#34419]). diff --git a/base/range.jl b/base/range.jl index 60a6aacf4dfb8..f4af1cb055f72 100644 --- a/base/range.jl +++ b/base/range.jl @@ -743,18 +743,20 @@ show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") ==(r::T, s::T) where {T<:AbstractRange} = - (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) + (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) ==(r::OrdinalRange, s::OrdinalRange) = - (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) + (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) ==(r::T, s::T) where {T<:Union{StepRangeLen,LinRange}} = - (first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s)) + (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s))) ==(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) where {T} = - (first(r) == first(s)) & (last(r) == last(s)) & (step(r) == step(s)) + (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) function ==(r::AbstractRange, s::AbstractRange) lr = length(r) if lr != length(s) return false + elseif iszero(lr) + return true end yr, ys = iterate(r), iterate(s) while yr !== nothing diff --git a/base/strings/util.jl b/base/strings/util.jl index 4b68190311efa..e7abfa0bf3f98 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -392,8 +392,8 @@ end function _split(str::AbstractString, splitter, limit::Integer, keepempty::Bool, strs::Array) i = 1 # firstindex(str) n = lastindex(str) - r = something(findfirst(splitter,str), 0) - if r != 0:-1 + r = findfirst(splitter,str) + if !isnothing(r) j, k = first(r), nextind(str,last(r)) while 0 < j <= n && length(strs) != limit-1 if i < k @@ -403,8 +403,8 @@ function _split(str::AbstractString, splitter, limit::Integer, keepempty::Bool, i = k end (k <= j) && (k = nextind(str,j)) - r = something(findnext(splitter,str,k), 0) - r == 0:-1 && break + r = findnext(splitter,str,k) + isnothing(r) && break j, k = first(r), nextind(str,last(r)) end end diff --git a/stdlib/Dates/test/ranges.jl b/stdlib/Dates/test/ranges.jl index 473940d1ce98b..f10350c3cb6f5 100644 --- a/stdlib/Dates/test/ranges.jl +++ b/stdlib/Dates/test/ranges.jl @@ -35,7 +35,7 @@ let @test first(reverse(dr)) < f1 @test last(reverse(dr)) >= f1 @test issorted(dr) - @test sortperm(dr) == 1:1:0 + @test sortperm(dr) === StepRange{Int64,Int}(1:1:0) @test !(f1 in dr) @test !(l1 in dr) @test !(f1 - pos_step in dr) @@ -93,7 +93,7 @@ let @test first(reverse(dr)) > l1 @test last(reverse(dr)) <= l1 @test issorted(dr) - @test sortperm(dr) == 1:1:0 + @test sortperm(dr) === StepRange{Int64,Int}(1:1:0) @test !(l1 in dr) @test !(l1 in dr) @test !(l1 - neg_step in dr) @@ -153,7 +153,7 @@ let @test first(reverse(dr)) < f1 @test last(reverse(dr)) >= f1 @test issorted(dr) - @test sortperm(dr) == 1:1:0 + @test sortperm(dr) === StepRange{Int64,Int}(1:1:0) @test !(f1 in dr) @test !(l1 in dr) @test !(f1 - pos_step in dr) @@ -211,7 +211,7 @@ let @test first(reverse(dr)) > l1 @test last(reverse(dr)) <= l1 @test issorted(dr) - @test sortperm(dr) == 1:1:0 + @test sortperm(dr) === StepRange{Int64,Int}(1:1:0) @test !(l1 in dr) @test !(l1 in dr) @test !(l1 - neg_step in dr) diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 545f47f438a29..d37bfd7f3ad7e 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -132,7 +132,7 @@ end let s = "Main.CompletionFoo." c, r = test_complete(s) @test "bar" in c - @test r == 20:19 + @test r === UnitRange{Int64}(20:19) @test s[r] == "" end @@ -592,7 +592,12 @@ end # The return type is of importance, before #8995 it would return nothing # which would raise an error in the repl code. -@test (String[], 0:-1, false) == test_scomplete("\$a") +let c, r, res + c, r, res = test_scomplete("\$a") + @test c == String[] + @test r === UnitRange{Int64}(0:-1) + @test res === false +end if Sys.isunix() let s, c, r @@ -640,7 +645,7 @@ let s, c, r s = "/tmp/" c,r = test_scomplete(s) @test !("tmp/" in c) - @test r == 6:5 + @test r === UnitRange{Int64}(6:5) @test s[r] == "" end @@ -657,7 +662,7 @@ let s, c, r file = joinpath(path, "repl completions") s = "/tmp " c,r = test_scomplete(s) - @test r == 6:5 + @test r === UnitRange{Int64}(6:5) end # Test completing paths with an escaped trailing space @@ -971,7 +976,7 @@ end let s = "" c, r = test_complete_context(s) @test "bar" in c - @test r == 1:0 + @test r === UnitRange{Int64}(1:0) @test s[r] == "" end diff --git a/test/core.jl b/test/core.jl index d4401a02c79ff..da814873820fd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6796,7 +6796,7 @@ function f27597(y) return y end @test f27597([1]) == [1] -@test f27597([]) == 1:0 +@test f27597([]) === 1:0 # issue #22291 wrap22291(ind) = (ind...,) diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 58a83cc2c9311..7479821be8268 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -502,7 +502,7 @@ v = OffsetArray(rand(8), (-2,)) @test sort(A, dims=2) == OffsetArray(sort(parent(A), dims=2), A.offsets) # Issue #33977 soa = OffsetArray([2,2,3], -2) -@test searchsorted(soa, 1) == -1:-2 +@test searchsorted(soa, 1) === -1:-2 @test searchsortedfirst(soa, 1) == -1 @test searchsortedlast(soa, 1) == -2 @test first(sort!(soa; alg=QuickSort)) == 2 diff --git a/test/ranges.jl b/test/ranges.jl index 91ad68db40c07..77f925b5af337 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -459,10 +459,10 @@ end end end @testset "indexing range with empty range (#4309)" begin - @test (3:6)[5:4] == 7:6 + @test (3:6)[5:4] === 7:6 @test_throws BoundsError (3:6)[5:5] @test_throws BoundsError (3:6)[5] - @test (0:2:10)[7:6] == 12:2:10 + @test (0:2:10)[7:6] === 12:2:10 @test_throws BoundsError (0:2:10)[7:7] end # indexing with negative ranges (#8351) @@ -818,7 +818,8 @@ end map(Int32,1:3:17), map(Int64,1:3:17), 1:0, 1:-1:0, 17:-3:0, 0.0:0.1:1.0, map(Float32,0.0:0.1:1.0),map(Float32,LinRange(0.0, 1.0, 11)), 1.0:eps():1.0 .+ 10eps(), 9007199254740990.:1.0:9007199254740994, - range(0, stop=1, length=20), map(Float32, range(0, stop=1, length=20))] + range(0, stop=1, length=20), map(Float32, range(0, stop=1, length=20)), + 3:2, 5:-2:7, range(0.0, step=2.0, length=0), 3//2:3//2:0//1, LinRange(2,3,0)] for r in Rs local r ar = Vector(r) @@ -838,6 +839,7 @@ end @test 1:1:10 == 1:10 == 1:10 == Base.OneTo(10) == Base.OneTo(10) @test 1:10 != 2:10 != 2:11 != Base.OneTo(11) @test Base.OneTo(10) != Base.OneTo(11) != 1:10 + @test Base.OneTo(0) == 5:4 end # issue #2959 @test 1.0:1.5 == 1.0:1.0:1.5 == 1.0:1.0 @@ -1555,11 +1557,11 @@ end for stops in [-2, 0, 2, 100] for lengths in [2, 10, 100] if stops >= starts - @test range(starts, stops, length=lengths) == range(starts, stop=stops, length=lengths) + @test range(starts, stops, length=lengths) === range(starts, stop=stops, length=lengths) end end for steps in [0.01, 1, 2] - @test range(starts, stops, step=steps) == range(starts, stop=stops, step=steps) + @test range(starts, stops, step=steps) === range(starts, stop=stops, step=steps) end end end diff --git a/test/regex.jl b/test/regex.jl index 6a32a49051d13..3ec6e2f222401 100644 --- a/test/regex.jl +++ b/test/regex.jl @@ -55,8 +55,8 @@ # findall @test findall(r"\w+", "foo bar") == [1:3, 5:7] @test findall(r"\w+", "foo bar", overlap=true) == [1:3, 2:3, 3:3, 5:7, 6:7, 7:7] - @test findall(r"\w*", "foo bar") == [1:3, 4:3, 5:7, 8:7] - @test findall(r"\b", "foo bar") == [1:0, 4:3, 5:4, 8:7] + @test all(findall(r"\w*", "foo bar") .=== [1:3, 4:3, 5:7, 8:7]) # use === to compare empty ranges + @test all(findall(r"\b", "foo bar") .=== [1:0, 4:3, 5:4, 8:7]) # use === to compare empty ranges # count @test count(r"\w+", "foo bar") == 2 diff --git a/test/sorting.jl b/test/sorting.jl index 07d7eb5741016..ad5438514261e 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -88,16 +88,16 @@ end @test searchsorted(fill(1, 15), 1, 6, 10, Forward) == 6:10 for R in numTypes, T in numTypes - @test searchsorted(R[1, 1, 2, 2, 3, 3], T(0)) == 1:0 + @test searchsorted(R[1, 1, 2, 2, 3, 3], T(0)) === 1:0 @test searchsorted(R[1, 1, 2, 2, 3, 3], T(1)) == 1:2 @test searchsorted(R[1, 1, 2, 2, 3, 3], T(2)) == 3:4 - @test searchsorted(R[1, 1, 2, 2, 3, 3], T(4)) == 7:6 - @test searchsorted(R[1, 1, 2, 2, 3, 3], 2.5) == 5:4 + @test searchsorted(R[1, 1, 2, 2, 3, 3], T(4)) === 7:6 + @test searchsorted(R[1, 1, 2, 2, 3, 3], 2.5) === 5:4 - @test searchsorted(1:3, T(0)) == 1:0 + @test searchsorted(1:3, T(0)) === 1:0 @test searchsorted(1:3, T(1)) == 1:1 @test searchsorted(1:3, T(2)) == 2:2 - @test searchsorted(1:3, T(4)) == 4:3 + @test searchsorted(1:3, T(4)) === 4:3 @test searchsorted(R[1:10;], T(1), by=(x -> x >= 5)) == 1:4 @test searchsorted(R[1:10;], T(10), by=(x -> x >= 5)) == 5:10 @@ -109,31 +109,31 @@ end rg_r = reverse(rg) rgv, rgv_r = [rg;], [rg_r;] for i = I - @test searchsorted(rg,i) == searchsorted(rgv,i) - @test searchsorted(rg_r,i,rev=true) == searchsorted(rgv_r,i,rev=true) + @test searchsorted(rg,i) === searchsorted(rgv,i) + @test searchsorted(rg_r,i,rev=true) === searchsorted(rgv_r,i,rev=true) end end rg = 0.0:0.01:1.0 for i = 2:101 @test searchsorted(rg, rg[i]) == i:i - @test searchsorted(rg, prevfloat(rg[i])) == i:i-1 - @test searchsorted(rg, nextfloat(rg[i])) == i+1:i + @test searchsorted(rg, prevfloat(rg[i])) === i:i-1 + @test searchsorted(rg, nextfloat(rg[i])) === i+1:i end rg_r = reverse(rg) for i = 1:100 @test searchsorted(rg_r, rg_r[i], rev=true) == i:i - @test searchsorted(rg_r, prevfloat(rg_r[i]), rev=true) == i+1:i - @test searchsorted(rg_r, nextfloat(rg_r[i]), rev=true) == i:i-1 + @test searchsorted(rg_r, prevfloat(rg_r[i]), rev=true) === i+1:i + @test searchsorted(rg_r, nextfloat(rg_r[i]), rev=true) === i:i-1 end @test searchsorted(1:10, 1, by=(x -> x >= 5)) == searchsorted([1:10;], 1, by=(x -> x >= 5)) @test searchsorted(1:10, 10, by=(x -> x >= 5)) == searchsorted([1:10;], 10, by=(x -> x >= 5)) - @test searchsorted([], 0) == 1:0 - @test searchsorted([1,2,3], 0) == 1:0 - @test searchsorted([1,2,3], 4) == 4:3 + @test searchsorted([], 0) === 1:0 + @test searchsorted([1,2,3], 0) === 1:0 + @test searchsorted([1,2,3], 4) === 4:3 @testset "issue 8866" begin @test searchsortedfirst(500:1.0:600, -1.0e20) == 1 @@ -194,11 +194,11 @@ end for v0 = (3:-1:1, 3.0:-1.0:1.0), v = (v0, collect(v0)) @test searchsorted(v, 3, rev=true) == 1:1 @test searchsorted(v, 3.0, rev=true) == 1:1 - @test searchsorted(v, 2.5, rev=true) == 2:1 + @test searchsorted(v, 2.5, rev=true) === 2:1 @test searchsorted(v, 2, rev=true) == 2:2 - @test searchsorted(v, 1.2, rev=true) == 3:2 + @test searchsorted(v, 1.2, rev=true) === 3:2 @test searchsorted(v, 1, rev=true) == 3:3 - @test searchsorted(v, 0.1, rev=true) == 4:3 + @test searchsorted(v, 0.1, rev=true) === 4:3 end end end diff --git a/test/strings/search.jl b/test/strings/search.jl index f952229afdfe2..8a7abaec50309 100644 --- a/test/strings/search.jl +++ b/test/strings/search.jl @@ -247,7 +247,7 @@ end for i = 1:lastindex(u8str) @test findnext("", u8str, i) == i:i-1 end -@test findfirst("", "") == 1:0 +@test findfirst("", "") === 1:0 # string backward search with a zero-char string for i = 1:lastindex(astr) @@ -256,7 +256,7 @@ end for i = 1:lastindex(u8str) @test findprev("", u8str, i) == i:i-1 end -@test findlast("", "") == 1:0 +@test findlast("", "") === 1:0 # string forward search with a zero-char regex for i = 1:lastindex(astr) @@ -384,7 +384,7 @@ s_18109 = "fooα🐨βcd3" @testset "findall" begin @test findall("fooo", "foo") == UnitRange{Int}[] @test findall("ing", "Spinning laughing dancing") == [6:8, 15:17, 23:25] - @test findall("", "foo") == [1:0, 2:1, 3:2, 4:3] + @test all(findall("", "foo") .=== [1:0, 2:1, 3:2, 4:3]) # use === to compare empty ranges @test findall("αβ", "blαh blαβ blαββy") == findall("αβ", "blαh blαβ blαββy", overlap=true) == [9:11, 16:18] @test findall("aa", "aaaaaa") == [1:2, 3:4, 5:6] @test findall("aa", "aaaaaa", overlap=true) == [1:2, 2:3, 3:4, 4:5, 5:6]