diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 93fe4fedde039..a9dcda9d389d0 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -83,6 +83,7 @@ module IteratorsMD CartesianIndex{N}(index::Integer...) where {N} = CartesianIndex{N}(index) CartesianIndex{N}() where {N} = CartesianIndex{N}(()) # Un-nest passed CartesianIndexes + CartesianIndex{N}(index::CartesianIndex{N}) where {N} = index CartesianIndex(index::Union{Integer, CartesianIndex}...) = CartesianIndex(flatten(index)) flatten(::Tuple{}) = () flatten(I::Tuple{Any}) = Tuple(I[1]) @@ -166,6 +167,19 @@ module IteratorsMD Base.iterate(::CartesianIndex) = error("iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`") + # ranges are deliberately disabled to prevent ambiguities with the colon constructor + Base.range_start_step_length(start::CartesianIndex, step::CartesianIndex, len::Integer) = + error("range with a specified length is deliberately unsupported for CartesianIndex arguments."* + " Use StepRangeLen($start, $step, $len) to construct this range") + + # show is special-cased to avoid the start:stop:step display, + # which constructs a CartesianIndices + # See #50784 + function show(io::IO, r::StepRangeLen{<:CartesianIndex}) + print(io, "StepRangeLen(", first(r), ", ", + step(r), ", ", length(r), ")") + end + # Iteration const OrdinalRangeInt = OrdinalRange{Int, Int} """ diff --git a/test/ranges.jl b/test/ranges.jl index 4f88d991181db..a052b6c474034 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -2535,3 +2535,24 @@ end a = StepRangeLen(1,2,3,2) @test a[UInt(1)] == -1 end + +@testset "StepRangeLen of CartesianIndex-es" begin + CIstart = CartesianIndex(2,3) + CIstep = CartesianIndex(1,1) + r = StepRangeLen(CIstart, CIstep, 4) + @test length(r) == 4 + @test first(r) == CIstart + @test step(r) == CIstep + @test last(r) == CartesianIndex(5,6) + @test r[2] == CartesianIndex(3,4) + + @test repr(r) == "StepRangeLen($CIstart, $CIstep, 4)" + + r = StepRangeLen(CartesianIndex(), CartesianIndex(), 3) + @test all(==(CartesianIndex()), r) + @test length(r) == 3 + @test repr(r) == "StepRangeLen(CartesianIndex(), CartesianIndex(), 3)" + + errmsg = ("deliberately unsupported for CartesianIndex", "StepRangeLen") + @test_throws errmsg range(CartesianIndex(1), step=CartesianIndex(1), length=3) +end