`copy(x::CartesianIndices)`

and `copy(x::LinearIndices)`

do not return the same type as the input argument.

I guess you could argue that it doesn’t make sense to copy an immutable. But perhaps you could also argue that trying to copy an immutable should either return the correct type or result in a “no matching method” error.

There is a precedent for defining `copy`

for immutables. Here’s a definition for copying ranges from Base:

```
# Ranges are immutable
copy(r::AbstractRange) = r
```

So let’s try copying `CartesianIndices`

and `LinearIndices`

```
dims = ntuple(d -> -1:1, 2)
CIs = CartesianIndices(dims)
LIs = LinearIndices(CIs)
```

```
julia> copy(CIs)
3×3 Array{CartesianIndex{2},2}:
CartesianIndex(-1, -1) CartesianIndex(-1, 0) CartesianIndex(-1, 1)
CartesianIndex(0, -1) CartesianIndex(0, 0) CartesianIndex(0, 1)
CartesianIndex(1, -1) CartesianIndex(1, 0) CartesianIndex(1, 1)
julia> copy(LIs)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
```

The fallback for `copy`

seems to go through `similar`

which returns an `Array`

for these types.

For non-standard indexing, an `OffsetArray`

is returned (if `OffsetArrays`

are in scope, otherwise there’s a no method matching error).

## Summary

```
dims = ntuple(d -> -1:1, 2)
CIs = CartesianIndices(Base.IdentityUnitRange.(dims))
LIs = LinearIndices(CIs)
```

```
julia> copy(CIs)
ERROR: MethodError: no method matching similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{CartesianIndex{2}}, ::Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}})
Closest candidates are:
similar(::AbstractArray, ::Type{T}) where T at abstractarray.jl:629
similar(::AbstractArray, ::Type{T}, ::Union{Integer, AbstractUnitRange}...) where T at abstractarray.jl:632
similar(::AbstractArray, ::Type{T}, ::Tuple{Vararg{Int64,N}}) where {T, N} at abstractarray.jl:640
...
Stacktrace:
[1] similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{CartesianIndex{2}}) at .\abstractarray.jl:629
[2] similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:628
[3] copymutable at .\abstractarray.jl:971 [inlined]
[4] copy(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:915
[5] top-level scope at REPL[4]:1
julia> copy(LIs)
ERROR: MethodError: no method matching similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{Int64}, ::Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}})
Closest candidates are:
similar(::AbstractArray, ::Type{T}) where T at abstractarray.jl:629
similar(::AbstractArray, ::Type{T}, ::Union{Integer, AbstractUnitRange}...) where T at abstractarray.jl:632
similar(::AbstractArray, ::Type{T}, ::Tuple{Vararg{Int64,N}}) where {T, N} at abstractarray.jl:640
...
Stacktrace:
[1] similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{Int64}) at .\abstractarray.jl:629
[2] similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:628
[3] copymutable at .\abstractarray.jl:971 [inlined]
[4] copy(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:915
[5] top-level scope at REPL[5]:1
```

Would it make sense to define the following `copy`

methods?

```
Base.copy(x::CartesianIndices) = x
Base.copy(x::LinearIndices) = x
```