Revision bc7ba3d5c8b2dab1c0e19537739b67c2da902d11 authored by Keno Fischer on 20 March 2024, 06:35:46 UTC, committed by GitHub on 20 March 2024, 06:35:46 UTC
This passes slightly more information into this function (the full
`inst` rather than just the `stmt`) in order to allow external absint to
access additional fields (the flags and the info) if necessary to make
concrete evaluation decisions. It also splits out the actual concrete
evaluation from the part that just maps the `inst` to a CodeInstance.
1 parent e0bb95a
Raw File
abstractarray.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Random, LinearAlgebra

isdefined(Main, :InfiniteArrays) || @eval Main include("testhelpers/InfiniteArrays.jl")
using .Main.InfiniteArrays

isdefined(Main, :StructArrays) || @eval Main include("testhelpers/StructArrays.jl")
using .Main.StructArrays

isdefined(Main, :FillArrays) || @eval Main include("testhelpers/FillArrays.jl")
using .Main.FillArrays

A = rand(5,4,3)
@testset "Bounds checking" begin
    @test checkbounds(Bool, A, 1, 1, 1) == true
    @test checkbounds(Bool, A, 5, 4, 3) == true
    @test checkbounds(Bool, A, 0, 1, 1) == false
    @test checkbounds(Bool, A, 1, 0, 1) == false
    @test checkbounds(Bool, A, 1, 1, 0) == false
    @test checkbounds(Bool, A, 6, 4, 3) == false
    @test checkbounds(Bool, A, 5, 5, 3) == false
    @test checkbounds(Bool, A, 5, 4, 4) == false
    @test checkbounds(Bool, A, 1) == true           # linear indexing
    @test checkbounds(Bool, A, 60) == true
    @test checkbounds(Bool, A, 61) == false
    @test checkbounds(Bool, A, 2, 2, 2, 1) == true  # extra indices
    @test checkbounds(Bool, A, 2, 2, 2, 2) == false
    @test checkbounds(Bool, A, 1, 1)  == false
    @test checkbounds(Bool, A, 1, 12) == false
    @test checkbounds(Bool, A, 5, 12) == false
    @test checkbounds(Bool, A, 1, 13) == false
    @test checkbounds(Bool, A, 6, 12) == false
end

@testset "single CartesianIndex" begin
    @test checkbounds(Bool, A, CartesianIndex((1, 1, 1))) == true
    @test checkbounds(Bool, A, CartesianIndex((5, 4, 3))) == true
    @test checkbounds(Bool, A, CartesianIndex((0, 1, 1))) == false
    @test checkbounds(Bool, A, CartesianIndex((1, 0, 1))) == false
    @test checkbounds(Bool, A, CartesianIndex((1, 1, 0))) == false
    @test checkbounds(Bool, A, CartesianIndex((6, 4, 3))) == false
    @test checkbounds(Bool, A, CartesianIndex((5, 5, 3))) == false
    @test checkbounds(Bool, A, CartesianIndex((5, 4, 4))) == false
    @test checkbounds(Bool, A, CartesianIndex((1,))) == false
    @test checkbounds(Bool, A, CartesianIndex((60,))) == false
    @test checkbounds(Bool, A, CartesianIndex((61,))) == false
    @test checkbounds(Bool, A, CartesianIndex((2, 2, 2, 1,))) == true
    @test checkbounds(Bool, A, CartesianIndex((2, 2, 2, 2,))) == false
    @test checkbounds(Bool, A, CartesianIndex((1, 1,)))  == false
    @test checkbounds(Bool, A, CartesianIndex((1, 12,))) == false
    @test checkbounds(Bool, A, CartesianIndex((5, 12,))) == false
    @test checkbounds(Bool, A, CartesianIndex((1, 13,))) == false
    @test checkbounds(Bool, A, CartesianIndex((6, 12,))) == false
end

@testset "mix of CartesianIndex and Int" begin
    @test checkbounds(Bool, A, CartesianIndex((1,)), 1, CartesianIndex((1,))) == true
    @test checkbounds(Bool, A, CartesianIndex((5, 4)), 3)  == true
    @test checkbounds(Bool, A, CartesianIndex((0, 1)), 1)  == false
    @test checkbounds(Bool, A, 1, CartesianIndex((0, 1)))  == false
    @test checkbounds(Bool, A, 1, 1, CartesianIndex((0,))) == false
    @test checkbounds(Bool, A, 6, CartesianIndex((4, 3)))  == false
    @test checkbounds(Bool, A, 5, CartesianIndex((5,)), 3) == false
    @test checkbounds(Bool, A, CartesianIndex((5,)), CartesianIndex((4,)), CartesianIndex((4,)))  == false
end

@testset "Infinite axes" begin
    r = OneToInf()
    @testset "CartesianIndices" begin
        C = CartesianIndices(size(r))
        ax = to_indices(r, (C,))[1]
        @test ax === r
    end
    @testset "LinearIndices" begin
        L = LinearIndices(size(r))
        ax = to_indices(r, (L,))[1]
        @test ax === L
    end
end

@testset "vector indices" begin
    @test checkbounds(Bool, A, 1:5, 1:4, 1:3) == true
    @test checkbounds(Bool, A, 0:5, 1:4, 1:3) == false
    @test checkbounds(Bool, A, 1:5, 0:4, 1:3) == false
    @test checkbounds(Bool, A, 1:5, 1:4, 0:3) == false
    @test checkbounds(Bool, A, 1:6, 1:4, 1:3) == false
    @test checkbounds(Bool, A, 1:5, 1:5, 1:3) == false
    @test checkbounds(Bool, A, 1:5, 1:4, 1:4) == false
    @test checkbounds(Bool, A, 1:60) == true
    @test checkbounds(Bool, A, 1:61) == false
    @test checkbounds(Bool, A, 2, 2, 2, 1:1) == true  # extra indices
    @test checkbounds(Bool, A, 2, 2, 2, 10:9) == true
    @test checkbounds(Bool, A, 2, 2, 2, 1:2) == false
    @test checkbounds(Bool, A, 1:5, 1:4) == false
    @test checkbounds(Bool, A, 1:5, 1:12) == false
    @test checkbounds(Bool, A, 1:5, 1:13) == false
    @test checkbounds(Bool, A, 1:6, 1:12) == false
end

@testset "logical" begin
    @test checkbounds(Bool, A, trues(5), trues(4), trues(3)) == true
    @test checkbounds(Bool, A, trues(6), trues(4), trues(3)) == false
    @test checkbounds(Bool, A, trues(5), trues(5), trues(3)) == false
    @test checkbounds(Bool, A, trues(5), trues(4), trues(4)) == false
    @test checkbounds(Bool, A, trues(60)) == true
    @test checkbounds(Bool, A, trues(61)) == false
    @test checkbounds(Bool, A, 2, 2, 2, trues(1)) == true  # extra indices
    @test checkbounds(Bool, A, 2, 2, 2, trues(2)) == false
    @test checkbounds(Bool, A, trues(5), trues(12)) == false
    @test checkbounds(Bool, A, trues(5), trues(13)) == false
    @test checkbounds(Bool, A, trues(6), trues(12)) == false
    @test checkbounds(Bool, A, trues(5, 4, 3)) == true
    @test checkbounds(Bool, A, trues(5, 4, 3, 1)) == true # issue 45867
    @test checkbounds(Bool, A, trues(5, 4, 2)) == false
    @test checkbounds(Bool, A, trues(5, 12)) == false
    @test checkbounds(Bool, A, trues(1, 5), trues(1, 4, 1), trues(1, 1, 3)) == false
    @test checkbounds(Bool, A, trues(1, 5), trues(1, 4, 1), trues(1, 1, 2)) == false
    @test checkbounds(Bool, A, trues(1, 5), trues(1, 5, 1), trues(1, 1, 3)) == false
    @test checkbounds(Bool, A, trues(1, 5), :, 2) == false
    @test checkbounds(Bool, A, trues(5, 4), trues(3)) == true
    @test checkbounds(Bool, A, trues(5), trues(4, 3, 1)) == true
    @test checkbounds(Bool, A, trues(5, 4), trues(3, 2)) == false
    @test checkbounds(Bool, A, trues(4, 4), trues(3)) == false
    @test checkbounds(Bool, A, trues(5, 4), trues(2)) == false
    @test checkbounds(Bool, A, trues(6, 4), trues(3)) == false
    @test checkbounds(Bool, A, trues(5, 4), trues(4)) == false
end

@testset "array of CartesianIndex" begin
    @test checkbounds(Bool, A, [CartesianIndex((1, 1, 1))]) == true
    @test checkbounds(Bool, A, [CartesianIndex((5, 4, 3))]) == true
    @test checkbounds(Bool, A, [CartesianIndex((0, 1, 1))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((1, 0, 1))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((1, 1, 0))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((6, 4, 3))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((5, 5, 3))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((5, 4, 4))]) == false
    @test checkbounds(Bool, A, [CartesianIndex((1, 1))], 1) == true
    @test checkbounds(Bool, A, [CartesianIndex((5, 4))], 3) == true
    @test checkbounds(Bool, A, [CartesianIndex((0, 1))], 1) == false
    @test checkbounds(Bool, A, [CartesianIndex((1, 0))], 1) == false
    @test checkbounds(Bool, A, [CartesianIndex((1, 1))], 0) == false
    @test checkbounds(Bool, A, [CartesianIndex((6, 4))], 3) == false
    @test checkbounds(Bool, A, [CartesianIndex((5, 5))], 3) == false
    @test checkbounds(Bool, A, [CartesianIndex((5, 4))], 4) == false
    @test checkbounds(Bool, A, 5, [CartesianIndex((4, 3, 1))]) == true
    @test checkbounds(Bool, A, 5, [CartesianIndex((4, 3, 2))]) == false
    @test_throws ArgumentError checkbounds(Bool, A, [CartesianIndex((4, 3)), CartesianIndex((4,))])
    @test_throws ArgumentError checkbounds(Bool, A, [CartesianIndex((1,)), 1])
end

@testset "index conversion" begin
    @testset "0-dimensional" begin
        for i in ((), fill(0))
            @test LinearIndices(i)[1] == 1
            @test_throws BoundsError LinearIndices(i)[2]
            @test_throws BoundsError LinearIndices(i)[1:2]
            @test LinearIndices(i)[1,1] == 1
            @test LinearIndices(i)[] == 1
            @test size(LinearIndices(i)) == ()
            @test CartesianIndices(i)[1] == CartesianIndex()
            @test_throws BoundsError CartesianIndices(i)[2]
            @test_throws BoundsError CartesianIndices(i)[1:2]
            io = IOBuffer()
            show(io, CartesianIndices(i))
            @test String(take!(io)) == "CartesianIndices(())"
        end
    end

    @testset "1-dimensional" begin
        for i = 1:3
            @test LinearIndices((3,))[i] == i
            @test CartesianIndices((3,))[i] == CartesianIndex(i,)
        end
        @test LinearIndices((3,))[2,1] == 2
        @test LinearIndices((3,))[[1]] == [1]
        @test size(LinearIndices((3,))) == (3,)
        @test LinearIndices((3,))[1:2] === 1:2
        @test LinearIndices((3,))[1:2:3] === 1:2:3
        @test_throws BoundsError LinearIndices((3,))[2:4]
        @test_throws BoundsError CartesianIndices((3,))[2,2]
        #   ambiguity btw cartesian indexing and linear indexing in 1d when
        #   indices may be nontraditional
        @test_throws ArgumentError Base._sub2ind((1:3,), 2)
        @test_throws ArgumentError Base._ind2sub((1:3,), 2)

        ci = CartesianIndices((2:4,))
        @test first(ci) == ci[1] == CartesianIndex(2)
        @test last(ci)  == ci[end] == ci[3] == CartesianIndex(4)
        li = LinearIndices(ci)
        @test collect(li) == [1,2,3]
        @test first(li) == li[1] == 1
        @test last(li)  == li[3] == 3
        io = IOBuffer()
        show(io, ci)
        @test String(take!(io)) == "CartesianIndices((2:4,))"
    end

    @testset "2-dimensional" begin
        k = 0
        cartesian = CartesianIndices((4,3))
        linear = LinearIndices(cartesian)
        @test size(cartesian) == size(linear) == (4, 3)
        for j = 1:3, i = 1:4
            k += 1
            @test linear[i,j] == linear[k] == k
            @test cartesian[k] == CartesianIndex(i,j)
            @test LinearIndices(map(Base.Slice, (0:3,3:5)))[i-1,j+2] == k
            @test CartesianIndices(map(Base.Slice, (0:3,3:5)))[k] == CartesianIndex(i-1,j+2)
        end
        @test linear[linear] == linear
        @test linear[vec(linear)] == vec(linear)
        @test linear[cartesian] == linear
        @test linear[vec(cartesian)] == vec(linear)
        @test cartesian[linear] == cartesian
        @test cartesian[vec(linear)] == vec(cartesian)
        @test cartesian[cartesian] == cartesian
        @test cartesian[vec(cartesian)] == vec(cartesian)
        @test linear[2:3] === 2:3
        @test linear[3:-1:1] === 3:-1:1
        @test_throws BoundsError linear[4:13]
        io = IOBuffer()
        show(io, cartesian)
        @test String(take!(io)) == "CartesianIndices((4, 3))"
    end

    @testset "3-dimensional" begin
        l = 0
        for k = 1:2, j = 1:3, i = 1:4
            l += 1
            @test LinearIndices((4,3,2))[i,j,k] == l
            @test LinearIndices((4,3,2))[l] == l
            @test CartesianIndices((4,3,2))[i,j,k] == CartesianIndex(i,j,k)
            @test CartesianIndices((4,3,2))[l] == CartesianIndex(i,j,k)
            @test LinearIndices((1:4,1:3,1:2))[i,j,k] == l
            @test LinearIndices((1:4,1:3,1:2))[l] == l
            @test CartesianIndices((1:4,1:3,1:2))[i,j,k] == CartesianIndex(i,j,k)
            @test CartesianIndices((1:4,1:3,1:2))[l] == CartesianIndex(i,j,k)
        end

        l = 0
        for k = -101:-100, j = 3:5, i = 0:3
            l += 1
            @test LinearIndices(map(Base.Slice, (0:3,3:5,-101:-100)))[i,j,k] == l
            @test LinearIndices(map(Base.Slice, (0:3,3:5,-101:-100)))[l] == l
            @test CartesianIndices(map(Base.Slice, (0:3,3:5,-101:-100)))[i,j,k] == CartesianIndex(i,j,k)
            @test CartesianIndices(map(Base.Slice, (0:3,3:5,-101:-100)))[l] == CartesianIndex(i,j,k)
        end

        local A = reshape(Vector(1:9), (3,3))
        @test CartesianIndices(size(A))[6] == CartesianIndex(3,2)
        @test LinearIndices(size(A))[3, 2] == 6
        @test CartesianIndices(A)[6] == CartesianIndex(3,2)
        @test LinearIndices(A)[3, 2] == 6
        for i in 1:length(A)
            @test LinearIndices(A)[CartesianIndices(A)[i]] == i
        end

        @testset "PR #9256" begin
            function pr9256()
                m = [1 2 3; 4 5 6; 7 8 9]
                Base._ind2sub(m, 6)
            end
            @test pr9256() == (3,2)
        end
    end
end

@testset "AbstractArray fallbacks for CartesianIndices" begin
    @test ndims(CartesianIndices{3}) == 3
    @test eltype(CartesianIndices{3}) == CartesianIndex{3}
    for t in ((1:2, 1:2), (3:4,), ())
        C2 = CartesianIndices(t)
        @test ndims(C2) == length(t)
        @test ndims(typeof(C2)) == length(t)
        @test IndexStyle(C2) == IndexCartesian()
        @test eltype(C2) == CartesianIndex{length(t)}
        @test Base.IteratorSize(C2) isa Base.HasShape{length(t)}
    end
end

@testset "LinearIndices" begin
    @testset "constructors" begin
        for oinds in [
            (2, 3),
            (UInt8(2), 3),
            (2, UInt8(3)),
            (2, 1:3),
            (Base.OneTo(2), 1:3)
        ]
            R = LinearIndices(oinds)
            @test size(R) == (2, 3)
            @test axes(R) == (Base.OneTo(2), Base.OneTo(3))
            @test R[begin] == 1
            @test R[end] == 6
        end

        for oinds in [(2, ), (2, 3), (2, 3, 4)]
            R = CartesianIndices(oinds)
            @test size(R) == oinds
        end
    end

    @testset "IdentityUnitRange" begin
        function _collect(A)
            rst = eltype(A)[]
            for i in A
                push!(rst, i)
            end
            rst
        end
        function _simd_collect(A)
            rst = eltype(A)[]
            @simd for i in A
                push!(rst, i)
            end
            rst
        end

        for oinds in [
            (Base.IdentityUnitRange(0:1),),
            (Base.IdentityUnitRange(0:1), Base.IdentityUnitRange(0:2)),
            (Base.IdentityUnitRange(0:1), Base.OneTo(3)),
        ]
            R = LinearIndices(oinds)
            @test axes(R) === oinds
            @test _collect(R) == _simd_collect(R) == vec(collect(R))
        end
        R = LinearIndices((Base.IdentityUnitRange(0:1), 0:1))
        @test axes(R) == (Base.IdentityUnitRange(0:1), Base.OneTo(2))
    end
end

# token type on which to dispatch testing methods in order to avoid potential
# name conflicts elsewhere in the base test suite
mutable struct TestAbstractArray end

## Tests for the abstract array interfaces with minimally defined array types

if !isdefined(@__MODULE__, :T24Linear)
    include("testhelpers/arrayindexingtypes.jl")
end

const can_inline = Base.JLOptions().can_inline != 0
function test_scalar_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where T
    N = prod(shape)
    A = reshape(Vector(1:N), shape)
    B = T(A)
    @test A == B
    # Test indexing up to 5 dimensions
    trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0)))
    trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0)))
    trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0)))
    trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0)))
    i=0
    for i5 = 1:size(B, 5)
        for i4 = 1:size(B, 4)
            for i3 = 1:size(B, 3)
                for i2 = 1:size(B, 2)
                    for i1 = 1:size(B, 1)
                        i += 1
                        @test A[i1,i2,i3,i4,i5,trailing5] == B[i1,i2,i3,i4,i5,trailing5] == i
                        @test A[i1,i2,i3,i4,i5,trailing5] ==
                              Base.unsafe_getindex(B, i1, i2, i3, i4, i5, trailing5) == i
                    end
                end
            end
        end
    end
    # Test linear indexing and partial linear indexing
    i=0
    for i1 = 1:length(B)
        i += 1
        @test A[i1] == B[i1] == i
    end
    i=0
    for i2 = 1:size(B, 2)
        for i1 = 1:size(B, 1)
            i += 1
            @test A[i1,i2,trailing2] == B[i1,i2,trailing2] == i
        end
    end
    @test A == B
    i=0
    for i3 = 1:size(B, 3)
        for i2 = 1:size(B, 2)
            for i1 = 1:size(B, 1)
                i += 1
                @test A[i1,i2,i3,trailing3] == B[i1,i2,i3,trailing3] == i
            end
        end
    end
    # Test zero-dimensional accesses
    @test A[1] == B[1] == 1
    # Test multidimensional scalar indexed assignment
    C = T(Int, shape)
    D1 = T(Int, shape)
    D2 = T(Int, shape)
    D3 = T(Int, shape)
    i=0
    for i5 = 1:size(B, 5)
        for i4 = 1:size(B, 4)
            for i3 = 1:size(B, 3)
                for i2 = 1:size(B, 2)
                    for i1 = 1:size(B, 1)
                        i += 1
                        C[i1,i2,i3,i4,i5,trailing5] = i
                        # test general unsafe_setindex!
                        Base.unsafe_setindex!(D1, i, i1,i2,i3,i4,i5,trailing5)
                        # test for dropping trailing dims
                        Base.unsafe_setindex!(D2, i, i1,i2,i3,i4,i5,trailing5, 1, 1, 1)
                        # test for expanding index argument to appropriate dims
                        Base.unsafe_setindex!(D3, i, i1,i2,i3,i4,trailing4)
                    end
                end
            end
        end
    end
    @test D1 == D2 == C == B == A
    @test D3[:, :, :, :, 1, trailing5] == D2[:, :, :, :, 1, trailing5]
    # Test linear indexing and partial linear indexing
    C = T(Int, shape)
    fill!(C, 0)
    @test C != B && C != A
    i=0
    for i1 = 1:length(C)
        i += 1
        C[i1] = i
    end
    @test C == B == A
    C = T(Int, shape)
    i=0
    C2 = reshape(C, Val(2))
    for i2 = 1:size(C2, 2)
        for i1 = 1:size(C2, 1)
            i += 1
            C2[i1,i2,trailing2] = i
        end
    end
    @test C == B == A
    C = T(Int, shape)
    i=0
    C3 = reshape(C, Val(3))
    for i3 = 1:size(C3, 3)
        for i2 = 1:size(C3, 2)
            for i1 = 1:size(C3, 1)
                i += 1
                C3[i1,i2,i3,trailing3] = i
            end
        end
    end
    @test C == B == A
    # Test zero-dimensional setindex
    if length(A) == 1
        A[] = 0; B[] = 0
        @test A[] == B[] == 0
        @test A == B
    else
        @test_throws BoundsError A[] = 0
        @test_throws BoundsError B[] = 0
        @test_throws BoundsError A[]
        @test_throws BoundsError B[]
    end
end

function test_vector_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where T
    @testset "test_vector_indexing{$(T)}" begin
        N = prod(shape)
        A = reshape(Vector(1:N), shape)
        B = T(A)
        trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0)))
        trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0)))
        trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0)))
        trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0)))
        idxs = rand(1:N, 3, 3, 3)
        @test B[idxs] == A[idxs] == idxs
        @test B[vec(idxs)] == A[vec(idxs)] == vec(idxs)
        @test B[:] == A[:] == 1:N
        @test B[1:end] == A[1:end] == 1:N
        @test B[:,:,trailing2] == A[:,:,trailing2] == B[:,:,1,trailing3] == A[:,:,1,trailing3]
            B[1:end,1:end,trailing2] == A[1:end,1:end,trailing2] == B[1:end,1:end,1,trailing3] == A[1:end,1:end,1,trailing3]

        @testset "Test with containers that aren't Int[]" begin
            @test B[[]] == A[[]] == []
            @test B[convert(Array{Any}, idxs)] == A[convert(Array{Any}, idxs)] == idxs
        end

        idx1 = rand(1:size(A, 1), 3)
        idx2 = rand(1:size(A, 2), 4, 5)
        @testset "Test adding dimensions with matrices" begin
            @test B[idx1, idx2, trailing2] == A[idx1, idx2, trailing2] == reshape(A[idx1, vec(idx2), trailing2], 3, 4, 5) == reshape(B[idx1, vec(idx2), trailing2], 3, 4, 5)
            @test B[1, idx2, trailing2] == A[1, idx2, trailing2] == reshape(A[1, vec(idx2), trailing2], 4, 5) == reshape(B[1, vec(idx2), trailing2], 4, 5)
        end
            # test removing dimensions with 0-d arrays
        @testset "test removing dimensions with 0-d arrays" begin
            idx0 = reshape([rand(1:size(A, 1))])
            @test B[idx0, idx2, trailing2] == A[idx0, idx2, trailing2] == reshape(A[idx0[], vec(idx2), trailing2], 4, 5) == reshape(B[idx0[], vec(idx2), trailing2], 4, 5)
            @test B[reshape([end]), reshape([end]), trailing2] == A[reshape([end]), reshape([end]), trailing2] == reshape([A[end,end,trailing2]]) == reshape([B[end,end,trailing2]])
        end

        mask = bitrand(shape)
        @testset "test logical indexing" begin
            let
                masks1 = (mask,)
                @test only(@inferred(to_indices(A, masks1))) isa Base.LogicalIndex{Int}
                if IndexStyle(B) isa IndexCartesian
                    @test only(@inferred(to_indices(B, masks1))) === Base.LogicalIndex(mask)
                end
            end
            @test B[mask] == A[mask] == B[findall(mask)] == A[findall(mask)] == LinearIndices(mask)[findall(mask)]
            @test B[vec(mask)] == A[vec(mask)] == LinearIndices(mask)[findall(mask)]
            mask1 = bitrand(size(A, 1))
            mask2 = bitrand(size(A, 2))
            @test B[mask1, mask2, trailing2] == A[mask1, mask2, trailing2] ==
                B[LinearIndices(mask1)[findall(mask1)], LinearIndices(mask2)[findall(mask2)], trailing2]
            @test B[mask1, 1, trailing2] == A[mask1, 1, trailing2] == LinearIndices(mask)[findall(mask1)]

            if ndims(B) > 1
                slice = ntuple(Returns(:), ndims(B)-1)
                maskfront = bitrand(shape[1:end-1])
                Bslicefront = B[slice..., 1]
                @test B[maskfront, 1] == Bslicefront[maskfront]
                @test size(B[maskfront, 1:1]) == (sum(maskfront), 1)
                maskend = bitrand(shape[2:end])
                Bsliceend = B[1, slice...]
                @test B[1 ,maskend] == Bsliceend[maskend]
                @test size(B[1:1, maskend]) == (1, sum(maskend))
            end
        end
    end
end

function test_primitives(::Type{T}, shape, ::Type{TestAbstractArray}) where T
    N = prod(shape)
    A = reshape(Vector(1:N), shape)
    B = T(A)

    # last(a)
    @test last(B) == B[lastindex(B)] == B[end] == A[end]
    @test lastindex(B) == lastindex(A) == last(LinearIndices(B))
    @test lastindex(B, 1) == lastindex(A, 1) == last(axes(B, 1))
    @test lastindex(B, 2) == lastindex(A, 2) == last(axes(B, 2))

    # first(a)
    @test first(B) == B[firstindex(B)] == B[begin] == B[1] == A[1] == A[begin]
    @test firstindex(B) == firstindex(A) == first(LinearIndices(B))
    @test firstindex(B, 1) == firstindex(A, 1) == first(axes(B, 1))
    @test firstindex(B, 2) == firstindex(A, 2) == first(axes(B, 2))

    @test !isassigned(B)
    # isassigned(a::AbstractArray, i::Integer...)
    j = rand(1:length(B))
    @test isassigned(B, j)
    if T == T24Linear
        @test !isassigned(B, length(B) + 1)
    end
    # isassigned(a::AbstractArray, i::CartesianIndex)
    @test isassigned(B, first(CartesianIndices(B)))
    ind = last(CartesianIndices(B))
    @test !isassigned(B, ind + oneunit(ind))
    # isassigned(a::AbstractArray, i::Union{Integer,CartesianIndex}...)
    @test isassigned(B, Int16.(first.(axes(B)))..., CartesianIndex(1,1))
    # Bool isn't a valid index
    @test_throws ArgumentError isassigned(B, Bool.(first.(axes(B)))..., CartesianIndex(1,1))
    @test_throws ArgumentError isassigned(B, Bool.(first.(axes(B)))...)
    @test_throws ArgumentError isassigned(B, true)
    @test_throws ArgumentError isassigned(B, false)

    # reshape(a::AbstractArray, dims::Dims)
    @test_throws DimensionMismatch reshape(B, (0, 1))

    # copyto!(dest::AbstractArray, src::AbstractArray)
    @test_throws BoundsError copyto!(Vector{Int}(undef, 10), [1:11...])

    # convert{T, N}(::Type{Array}, A::AbstractArray{T, N})
    X = [1:10...]
    Y = [1 2; 3 4]
    @test convert(Array, X) == X
    @test convert(Array, Y) == Y

    # convert{T}(::Type{Vector}, A::AbstractVector{T})
    @test convert(Vector, X) == X
    @test convert(Vector, view(X, 2:4)) == [2,3,4]
    @test_throws MethodError convert(Vector, Y)

    # convert{T}(::Type{Matrix}, A::AbstractMatrix{T})
    @test convert(Matrix, Y) == Y
    @test convert(Matrix, view(Y, 1:2, 1:2)) == Y
    @test_throws MethodError convert(Matrix, X)
end

mutable struct TestThrowNoGetindex{T} <: AbstractVector{T} end
@testset "ErrorException if getindex is not defined" begin
    Base.length(::TestThrowNoGetindex) = 2
    Base.size(::TestThrowNoGetindex) = (2,)
    @test_throws Base.CanonicalIndexError isassigned(TestThrowNoGetindex{Float64}(), 1)
end

function test_in_bounds(::Type{TestAbstractArray})
    n = rand(2:5)
    sz = rand(2:5, n)
    len = prod(sz)
    A = zeros(sz...)
    for i in 1:len
        @test checkbounds(Bool, A, i) == true
    end
    @test checkbounds(Bool, A, len + 1) == false
end

mutable struct UnimplementedFastArray{T, N} <: AbstractArray{T, N} end
Base.IndexStyle(::UnimplementedFastArray) = Base.IndexLinear()

mutable struct UnimplementedSlowArray{T, N} <: AbstractArray{T, N} end
Base.IndexStyle(::UnimplementedSlowArray) = Base.IndexCartesian()

mutable struct UnimplementedArray{T, N} <: AbstractArray{T, N} end

function test_getindex_internals(::Type{T}, shape, ::Type{TestAbstractArray}) where T
    N = prod(shape)
    A = reshape(Vector(1:N), shape)
    B = T(A)

    @test getindex(A, 1) == 1
    @test getindex(B, 1) == 1
    @test Base.unsafe_getindex(A, 1) == 1
    @test Base.unsafe_getindex(B, 1) == 1
end

function test_getindex_internals(::Type{TestAbstractArray})
    U = UnimplementedFastArray{Int, 2}()
    V = UnimplementedSlowArray{Int, 2}()
    @test_throws Base.CanonicalIndexError getindex(U, 1)
    @test_throws Base.CanonicalIndexError Base.unsafe_getindex(U, 1)
    @test_throws Base.CanonicalIndexError getindex(V, 1, 1)
    @test_throws Base.CanonicalIndexError Base.unsafe_getindex(V, 1, 1)
end

function test_setindex!_internals(::Type{T}, shape, ::Type{TestAbstractArray}) where T
    N = prod(shape)
    A = reshape(Vector(1:N), shape)
    B = T(A)

    Base.unsafe_setindex!(B, 2, 1)
    @test B[1] == 2
end

function test_setindex!_internals(::Type{TestAbstractArray})
    U = UnimplementedFastArray{Int, 2}()
    V = UnimplementedSlowArray{Int, 2}()
    @test_throws Base.CanonicalIndexError setindex!(U, 0, 1)
    @test_throws Base.CanonicalIndexError Base.unsafe_setindex!(U, 0, 1)
    @test_throws Base.CanonicalIndexError setindex!(V, 0, 1, 1)
    @test_throws Base.CanonicalIndexError Base.unsafe_setindex!(V, 0, 1, 1)
end

function test_get(::Type{TestAbstractArray})
    A = T24Linear(reshape([1:24...], 4, 3, 2))
    B = TSlow(reshape([1:24...], 4, 3, 2))

    @test get(A, (), 0) == 0
    @test get(B, (), 0) == 0
    @test get(A, (1,), 0) == get(A, 1, 0) == A[1] == 1
    @test get(B, (1,), 0) == get(B, 1, 0) == B[1] == 1
    @test get(A, (25,), 0) == get(A, 25, 0) == 0
    @test get(B, (25,), 0) == get(B, 25, 0) == 0
    @test get(A, (1,1,1), 0) == A[1,1,1] == 1
    @test get(B, (1,1,1), 0) == B[1,1,1] == 1
    @test get(A, (1,1,3), 0) == 0
    @test get(B, (1,1,3), 0) == 0

    @test get(TSlow([]), (), 0) == 0
    @test get(TSlow([1]), (), 0) == 1
    @test get(TSlow(fill(1)), (), 0) == 1

    global c = 0
    f() = (global c = c+1; 0)
    @test get(f, A, ()) == 0
    @test c == 1
    @test get(f, B, ()) == 0
    @test c == 2
    @test get(f, A, (1,)) == get(f, A, 1) == A[1] == 1
    @test c == 2
    @test get(f, B, (1,)) == get(f, B, 1) == B[1] == 1
    @test c == 2
    @test get(f, A, (25,)) == get(f, A, 25) == 0
    @test c == 4
    @test get(f, B, (25,)) == get(f, B, 25) == 0
    @test c == 6
    @test get(f, A, (1,1,1)) == A[1,1,1] == 1
    @test get(f, B, (1,1,1)) == B[1,1,1] == 1
    @test get(f, A, (1,1,3)) == 0
    @test c == 7
    @test get(f, B, (1,1,3)) == 0
    @test c == 8
    @test get(f, TSlow([]), ()) == 0
    @test c == 9
    @test get(f, TSlow([1]), ()) == 1
    @test get(f, TSlow(fill(1)), ()) == 1
end

function test_cat(::Type{TestAbstractArray})
    A = T24Linear([1:24...])
    b_int = reshape([1:27...], 3, 3, 3)
    b_float = reshape(Float64[1:27...], 3, 3, 3)
    b2hcat = Array{Float64}(undef, 3, 6, 3)
    b2vcat = Array{Float64}(undef, 6, 3, 3)
    b1 = reshape([1:9...], 3, 3)
    b2 = reshape([10:18...], 3, 3)
    b3 = reshape([19:27...], 3, 3)
    b2hcat[:, :, 1] = hcat(b1, b1)
    b2hcat[:, :, 2] = hcat(b2, b2)
    b2hcat[:, :, 3] = hcat(b3, b3)
    b2vcat[:, :, 1] = vcat(b1, b1)
    b2vcat[:, :, 2] = vcat(b2, b2)
    b2vcat[:, :, 3] = vcat(b3, b3)
    b3hcat = Array{Float64}(undef, 3, 9, 3)
    b3hcat[:, :, 1] = hcat(b1, b1, b1)
    b3hcat[:, :, 2] = hcat(b2, b2, b2)
    b3hcat[:, :, 3] = hcat(b3, b3, b3)
    b3vcat = Array{Float64}(undef, 9, 3, 3)
    b3vcat[:, :, 1] = vcat(b1, b1, b1)
    b3vcat[:, :, 2] = vcat(b2, b2, b2)
    b3vcat[:, :, 3] = vcat(b3, b3, b3)
    B = TSlow(b_int)
    B1 = TSlow([1:24...])
    B2 = TSlow([1:25...])
    C1 = TSlow([1 2; 3 4])
    C2 = TSlow([1 2 3; 4 5 6])
    C3 = TSlow([1 2; 3 4; 5 6])
    D = [1:24...]
    i = rand(1:10)

    @test cat(;dims=i) == Any[]
    @test Base.typed_hcat(Float64) == Vector{Float64}()
    @test Base.typed_vcat(Float64) == Vector{Float64}()
    @test vcat() == Any[]
    @test hcat() == Any[]
    @test vcat(1, 1.0, 3, 3.0) == [1.0, 1.0, 3.0, 3.0]
    @test hcat(1, 1.0, 3, 3.0) == [1.0 1.0 3.0 3.0]
    @test_throws DimensionMismatch hcat(B1, B2)
    @test_throws DimensionMismatch vcat(C1, C2)

    @test vcat(B) == B
    @test hcat(B) == B
    @test Base.typed_vcat(Float64, B) == TSlow(b_float)
    @test Base.typed_vcat(Float64, B, B) == TSlow(b2vcat)
    @test Base.typed_vcat(Float64, B, B, B) == TSlow(b3vcat)
    @test Base.typed_hcat(Float64, B) == TSlow(b_float)
    @test Base.typed_hcat(Float64, B, B) == TSlow(b2hcat)
    @test Base.typed_hcat(Float64, B, B, B) == TSlow(b3hcat)

    @testset "issue #49676, bad error message on v[1 +1]" begin
        # This is here because all these expressions are handled by Base.typed_hcat
        v = [1 2 3]
        @test_throws ArgumentError v[1 +1]
        @test_throws ArgumentError v[1 1]
        @test_throws ArgumentError v[[1 2] [2 3]]
    end

    @test vcat(B1, B2) == TSlow(vcat([1:24...], [1:25...]))
    @test hcat(C1, C2) == TSlow([1 2 1 2 3; 3 4 4 5 6])
    @test hcat(C1, C2, C1) == TSlow([1 2 1 2 3 1 2; 3 4 4 5 6 3 4])

    # hvcat
    for nbc in (1, 2, 3, 4, 5, 6)
        @test hvcat(nbc, 1:120...) == reshape([1:120...], nbc, round(Int, 120 / nbc))'
    end

    @test_throws ArgumentError hvcat(7, 1:20...)
    @test_throws DimensionMismatch hvcat((2), C1, C3)
    @test_throws DimensionMismatch hvcat((1), C1, C2)
    @test_throws DimensionMismatch hvcat((1), C2, C3)

    tup = tuple(rand(1:10, i)...)
    @test hvcat(tup) == []

    # check for shape mismatch
    @test_throws ArgumentError hvcat((2, 2), 1, 2, 3, 4, 5)
    @test_throws ArgumentError Base.typed_hvcat(Int, (2, 2), 1, 2, 3, 4, 5)
    # check for # of columns mismatch b/w rows
    @test_throws DimensionMismatch hvcat((3, 2), 1, 2, 3, 4, 5, 6)
    @test_throws DimensionMismatch Base.typed_hvcat(Int, (3, 2), 1, 2, 3, 4, 5, 6)

    # 18395
    @test isa(Any["a" 5; 2//3 1.0][2,1], Rational{Int})

    # 13665, 19038
    @test @inferred(hcat([1.0 2.0], 3))::Array{Float64,2} == [1.0 2.0 3.0]
    @test @inferred(vcat([1.0, 2.0], 3))::Array{Float64,1} == [1.0, 2.0, 3.0]

    @test @inferred(vcat(["a"], "b"))::Vector{String} == ["a", "b"]
    @test @inferred(vcat((1,), (2.0,)))::Vector{Tuple{Real}} == [(1,), (2.0,)]

    # 29172
    @test_throws ArgumentError cat([1], [2], dims=0)
    @test_throws ArgumentError cat([1], [2], dims=[5, -3])

    # 36041
    @test_throws MethodError cat(["a"], ["b"], dims=[1, 2])
    @test cat([1], [1], dims=[1, 2]) == I(2)

    # inferrability
    As = [zeros(2, 2) for _ = 1:2]
    @test @inferred(cat(As...; dims=Val(3))) == zeros(2, 2, 2)
    cat3v(As) = cat(As...; dims=Val(3))
    @test @inferred(cat3v(As)) == zeros(2, 2, 2)
    @test @inferred(cat(As...; dims=Val((1,2)))) == zeros(4, 4)

    r = rand(Float32, 56, 56, 64, 1);
    f(r) = cat(r, r, dims=(3,))
    @inferred f(r);
end

function test_ind2sub(::Type{TestAbstractArray})
    n = rand(2:5)
    dims = tuple(rand(1:5, n)...)
    len = prod(dims)
    A = reshape(Vector(1:len), dims...)
    I = CartesianIndices(dims)
    for i in 1:len
        @test A[I[i]] == A[i]
    end
end

# A custom linear slow array that insists upon Cartesian indexing
mutable struct TSlowNIndexes{T,N} <: AbstractArray{T,N}
    data::Array{T,N}
end
Base.IndexStyle(::Type{A}) where {A<:TSlowNIndexes} = Base.IndexCartesian()
Base.size(A::TSlowNIndexes) = size(A.data)
Base.getindex(A::TSlowNIndexes, index::Int...) = error("Must use $(ndims(A)) indices")
Base.getindex(A::TSlowNIndexes{T,2}, i::Int, j::Int) where {T} = A.data[i,j]


@testset "issue #15689, mapping an abstract type" begin
    @test isa(map(Set, Array[[1,2],[3,4]]), Vector{Set{Int}})
end

@testset "mapping over scalars" begin
    @test map(sin, 1) === sin(1)
end

function test_UInt_indexing(::Type{TestAbstractArray})
    A = [1:100...]
    _A = Expr(:quote, A)
    for i in 1:100
        _i8 = convert(UInt8, i)
        _i16 = convert(UInt16, i)
        _i32 = convert(UInt32, i)
        for _i in (_i8, _i16, _i32)
            @eval begin
                @test $_A[$_i] == $i
            end
        end
    end
end

# Issue 13315
function test_13315(::Type{TestAbstractArray})
    U = UInt(1):UInt(2)
    @test [U;[U;]] == [UInt(1), UInt(2), UInt(1), UInt(2)]
end

# checksquare
function test_checksquare()
    @test LinearAlgebra.checksquare(zeros(2,2)) == 2
    @test LinearAlgebra.checksquare(zeros(2,2),zeros(3,3)) == [2,3]
    @test_throws DimensionMismatch LinearAlgebra.checksquare(zeros(2,3))
end

#----- run tests -------------------------------------------------------------#

@testset for T in (T24Linear, TSlow), shape in ((24,), (2, 12), (2,3,4), (1,2,3,4), (4,3,2,1))
    test_scalar_indexing(T, shape, TestAbstractArray)
    test_vector_indexing(T, shape, TestAbstractArray)
    test_primitives(T, shape, TestAbstractArray)
    test_getindex_internals(T, shape, TestAbstractArray)
    test_setindex!_internals(T, shape, TestAbstractArray)
end
test_in_bounds(TestAbstractArray)
test_getindex_internals(TestAbstractArray)
test_setindex!_internals(TestAbstractArray)
test_get(TestAbstractArray)
test_cat(TestAbstractArray)
test_ind2sub(TestAbstractArray)

include("generic_map_tests.jl")
generic_map_tests(map, map!)
@test_throws ArgumentError map!(-, [1])

test_UInt_indexing(TestAbstractArray)
test_13315(TestAbstractArray)
test_checksquare()

A = TSlowNIndexes(rand(2,2))
@test_throws ErrorException A[1]
@test A[1,1] == A.data[1]
@test first(A) == A.data[1]

@testset "#16381" begin
    @inferred size(rand(3,2,1))
    @inferred size(rand(3,2,1), 2)

    @test @inferred(axes(rand(3,2)))    == (1:3,1:2)
    @test @inferred(axes(rand(3,2,1)))  == (1:3,1:2,1:1)
    @test @inferred(axes(rand(3,2), 1)) == 1:3
    @test @inferred(axes(rand(3,2), 2)) == 1:2
    @test @inferred(axes(rand(3,2), 3)) == 1:1
end

@testset "isinteger and isreal" begin
    @test all(isinteger, Diagonal(rand(1:5,5)))
    @test isreal(Diagonal(rand(5)))
end

@testset "unary ops" begin
    let A = Diagonal(rand(1:5,5))
        @test +(A) == A
        @test *(A) == A
    end
end

@testset "reverse dim on empty" begin
    @test reverse(Diagonal([]),dims=1) == Diagonal([])
end

@testset "ndims and friends" begin
    @test ndims(Diagonal(rand(1:5,5))) == 2
    @test ndims(Diagonal{Float64}) == 2
    @test ndims(Diagonal) == 2
    @test ndims(Vector) == 1
    @test ndims(Matrix) == 2
    @test ndims(Array{<:Any, 0}) == 0
    @test_throws MethodError ndims(Array)
end

@testset "Issue #17811" begin
    A17811 = Integer[]
    I = [abs(x) for x in A17811]
    @test isa(I, Array{Any,1})
    push!(I, 1)
    @test I == Any[1]
    @test isa(map(abs, A17811), Array{Any,1})
end

@testset "copymutable for itrs" begin
    @test Base.copymutable((1,2,3)) == [1,2,3]
end

@testset "_sub2ind for empty tuple" begin
    @test Base._sub2ind(()) == 1
end

@testset "to_shape" begin
    @test Base.to_shape(()) === ()
    @test Base.to_shape(1) === 1
    @test Base.to_shape(big(1)) === Base.to_shape(1)
    @test Base.to_shape(Int8(1)) === Base.to_shape(1)
end

@testset "issue #39923: similar" begin
    for ax in [(big(2), big(3)), (big(2), 3), (UInt64(2), 3), (2, UInt32(3)),
        (big(2), Base.OneTo(3)), (Base.OneTo(2), Base.OneTo(big(3)))]

        A = similar(ones(), Int, ax)
        @test axes(A) === (Base.OneTo(2), Base.OneTo(3))
        @test eltype(A) === Int
    end
end

@testset "issue #19267" begin
    @test ndims((1:3)[:]) == 1
    @test ndims((1:3)[:,:]) == 2
    @test ndims((1:3)[:,[1],:]) == 3
    @test ndims((1:3)[:,[1],:,[1]]) == 4
    @test ndims((1:3)[:,[1],1:1,:]) == 4
    @test ndims((1:3)[:,:,1:1,:]) == 4
    @test ndims((1:3)[:,:,1:1]) == 3
    @test ndims((1:3)[:,:,1:1,:,:,[1]]) == 6
end

@testset "issue #38192" begin
    img = cat([1 2; 3 4], [1 5; 6 7]; dims=3)
    mask = img[:,:,1] .== img[:,:,2]
    img[mask,2] .= 0
    @test img == cat([1 2; 3 4], [0 5; 6 7]; dims=3)
end

@testset "dispatch loop introduced in #19305" begin
    Z22, O33 = fill(0, 2, 2), fill(1, 3, 3)
    @test [(1:2) Z22; O33] == [[1,2] Z22; O33] == [[1 2]' Z22; O33]
end

@testset "checkbounds_indices method ambiguities #20989" begin
    @test Base.checkbounds_indices(Bool, (1:1,), ([CartesianIndex(1)],))
end

# keys, values, pairs
for A in (rand(2), rand(2,3))
    local A
    for (i, v) in pairs(A)
        @test A[i] == v
    end
    @test Array(values(A)) == A

     @test keytype(A) == keytype(typeof(A)) == eltype(keys(A))
     @test valtype(A) == valtype(typeof(A)) == eltype(values(A))
end

# nextind and prevind
@test nextind(zeros(4), 2) == 3
@test nextind(zeros(2,3), CartesianIndex(2,1)) == CartesianIndex(1, 2)
@test prevind(zeros(4), 2) == 1
@test prevind(zeros(2,3), CartesianIndex(2,1)) == CartesianIndex(1, 1)

@testset "ImageCore #40" begin
    Base.convert(::Type{Array{T,n}}, a::Array{T,n}) where {T<:Number,n} = a
    Base.convert(::Type{Array{T,n}}, a::Array) where {T<:Number,n} =
        copyto!(Array{T,n}(undef, size(a)), a)
    @test isa(empty(Dict(:a=>1, :b=>2.0), Union{}, Union{}), Dict{Union{}, Union{}})
end

@testset "zero-dimensional copy" begin
    Z = Array{Int,0}(undef); Z[] = 17
    @test Z == Array(Z) == copy(Z)
end

@testset "empty" begin
    @test isempty([])
    v = [1, 2, 3]
    v2 = empty(v)
    v3 = empty(v, Float64)
    @test !isempty(v)
    empty!(v)
    @test isempty(v)
    @test isempty(v2::Vector{Int})
    @test isempty(v3::Vector{Float64})

    S = StructArrays.StructArray{Complex{Int}}((v, v))
    for T in (Complex{Int}, ComplexF64)
        S0 = empty(S, T)
        @test S0 isa StructArrays.StructArray{T}
        @test length(S0) == 0
    end
    S0 = empty(S, String)
    @test S0 isa Vector{String}
    @test length(S0) == 0
end

@testset "CartesianIndices" begin
    xrng = 2:4
    yrng = 1:5
    CR = CartesianIndices(map(Base.Slice, (xrng,yrng)))

    for i in xrng, j in yrng
        @test CR[i,j] == CartesianIndex(i,j)
    end

    for i_lin in LinearIndices(CR)
        i = (i_lin-1) % length(xrng) + 1
        j = (i_lin-i) ÷ length(xrng) + 1
        @test CR[i_lin] == CartesianIndex(xrng[i],yrng[j])
    end

    @test CartesianIndices(fill(1., 2, 3)) == CartesianIndices((2,3))
    @test LinearIndices((2,3)) == [1 3 5; 2 4 6]

    for IType in (CartesianIndices, LinearIndices)
        I1 = IType((Base.OneTo(3),))
        I2 = IType((1:3,))
        @test !(I1 === I2)
        J1, J2 = @inferred(promote(I1, I2))
        @test J1 === J2
    end

    i = CartesianIndex(17,-2)
    @test CR .+ i === i .+ CR === CartesianIndices((19:21, -1:3)) == collect(CR) .+ i
    @test CR .- i === CartesianIndices((-15:-13, 3:7)) == collect(CR) .- i
    @test collect(i .- CR) == Ref(i) .- collect(CR) == i .- collect(CR)
end

@testset "issue #25770" begin
    @test vcat(1:3, fill(1, (2,1))) == vcat([1:3;], fill(1, (2,1))) == reshape([1,2,3,1,1], 5,1)
    @test hcat(1:2, fill(1, (2,1))) == hcat([1:2;], fill(1, (2,1))) == reshape([1,2,1,1],2,2)
    @test [(1:3) (4:6); fill(1, (3,2))] == reshape([1,2,3,1,1,1,4,5,6,1,1,1], 6,2)
end

@testset "copy!" begin
    @testset "AbstractVector" begin
        s = Vector([1, 2])
        for a = ([1], UInt[1], [3, 4, 5], UInt[3, 4, 5])
            @test s === copy!(s, Vector(a)) == Vector(a)
        end
        # issue #35649
        s = [1, 2, 3, 4]
        s2 = reshape(s, 2, 2) # shared data
        @test s === copy!(s, 11:14) == 11:14
    end
    @testset "AbstractArray" begin
        @test_throws ArgumentError copy!(zeros(2, 3), zeros(3, 2))
        s = zeros(2, 2)
        @test s === copy!(s, fill(1, 2, 2)) == fill(1, 2, 2)
        @test s === copy!(s, fill(1.0, 2, 2)) == fill(1.0, 2, 2)
    end
end

@testset "map on Dicts/Sets is forbidden" begin
    @test_throws ErrorException map(identity, Set([1,2,3]))
    @test_throws ErrorException map(identity, Dict("a"=>"b"))
end

@testset "Issue 30145" begin
    X = [1,2,3]
    @test isempty(X[Union{}[]])
end

@testset "Issue 30259" begin
    A = randn(1,2,3)
    @test get(A, CartesianIndex(1,2,3), :some_default) === A[1,2,3]
    @test get(A, CartesianIndex(2,2,3), :some_default) === :some_default
    @test get(11:15, CartesianIndex(6), nothing) === nothing
    @test get(11:15, CartesianIndex(5), nothing) === 15
end

@testset "IndexStyle for various types" begin
    @test Base.IndexStyle(UpperTriangular) == IndexCartesian() # subtype of AbstractArray, not of Array
    @test Base.IndexStyle(Vector) == IndexLinear()
    @test Base.IndexStyle(Memory) == IndexLinear()
    @test Base.IndexStyle(UnitRange) == IndexLinear()
    @test Base.IndexStyle(UpperTriangular(rand(3, 3)), [1; 2; 3]) == IndexCartesian()
    @test Base.IndexStyle(UpperTriangular(rand(3, 3)), rand(3, 3), [1; 2; 3]) == IndexCartesian()
    @test Base.IndexStyle(rand(3, 3), [1; 2; 3]) == IndexLinear()
end

@testset "promote_shape for Tuples and Dims" begin
    @test promote_shape((2, 1), (2,)) == (2, 1)
    @test_throws DimensionMismatch promote_shape((2, 3), (2,))
    @test promote_shape(Dims((2, 1)), Dims((2,))) == (2, 1)
    @test_throws DimensionMismatch promote_shape(Dims((2, 2)), Dims((2,)))
    @test_throws DimensionMismatch promote_shape(Dims((2, 3, 1)), Dims((2,2)))
end

@testset "getindex and setindex! for Ref" begin
    for x in [Ref(1), Ref([1,2,3], 1)]
        @test getindex(x) == getindex(x, CartesianIndex()) == 1
        x[CartesianIndex()] = 10
        @test getindex(x) == getindex(x, CartesianIndex()) == 10
    end
end

@testset "vcat with mixed elements" begin
    @test vcat(Nothing[], [missing], [1.0], [Int8(1)]) isa Vector{Union{Missing, Nothing, Float64}}
end

@testset "sizeof" begin
    let arrUInt8 = zeros(UInt8, 10)
        @test sizeof(arrUInt8) == 10
        @test Core.sizeof(arrUInt8) == 3 * sizeof(Int)
    end

    let arrUInt32 = zeros(UInt32, 10)
        @test sizeof(arrUInt32) == 40
        @test Core.sizeof(arrUInt32) == 3 * sizeof(Int)
    end

    let arrFloat64 = zeros(Float64, 10, 10)
        @test sizeof(arrFloat64) == 800
        @test Core.sizeof(arrFloat64) == 4 * sizeof(Int)
    end

    # Test union arrays (Issue #23321)
    let arrUnion = Union{Int64, Cvoid}[rand(Bool) ? k : nothing for k = 1:10]
        @test sizeof(arrUnion) == 80
        @test Core.sizeof(arrUnion) == 3 * sizeof(Int)
    end

    # Test non-power of 2 types (Issue #35884)
    primitive type UInt48 48 end
    UInt48(x::UInt64) = Core.Intrinsics.trunc_int(UInt48, x)
    UInt48(x::UInt32) = Core.Intrinsics.zext_int(UInt48, x)

    a = UInt48(0x00000001);
    b = UInt48(0x00000002);
    c = UInt48(0x00000003);
    let arrayOfUInt48 = [a, b, c]
        f35884(x) = sizeof(x)
        @test f35884(arrayOfUInt48) == 24
        @test Core.sizeof(arrayOfUInt48) == 3 * sizeof(Int)
    end
end

struct Strider{T,N} <: AbstractArray{T,N}
    data::Vector{T}
    offset::Int
    strides::NTuple{N,Int}
    size::NTuple{N,Int}
end
function Strider{T}(strides::NTuple{N}, size::NTuple{N}) where {T,N}
    offset = 1-sum(strides .* (strides .< 0) .* (size .- 1))
    data = Array{T}(undef, sum(abs.(strides) .* (size .- 1)) + 1)
    return Strider{T, N, Vector{T}}(data, offset, strides, size)
end
function Strider(vec::AbstractArray{T}, strides::NTuple{N}, size::NTuple{N}) where {T,N}
    offset = 1-sum(strides .* (strides .< 0) .* (size .- 1))
    @assert length(vec) >= sum(abs.(strides) .* (size .- 1)) + 1
    return Strider{T, N}(vec, offset, strides, size)
end
Base.size(S::Strider) = S.size
function Base.getindex(S::Strider{<:Any,N}, I::Vararg{Int,N}) where {N}
    return S.data[sum(S.strides .* (I .- 1)) + S.offset]
end
Base.strides(S::Strider) = S.strides
Base.elsize(::Type{<:Strider{T}}) where {T} = Base.elsize(Vector{T})
Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = MemoryRef(S.data.ref, S.offset)

@testset "Simple 3d strided views and permutes" for sz in ((5, 3, 2), (7, 11, 13))
    A = collect(reshape(1:prod(sz), sz))
    S = Strider(vec(A), strides(A), sz)
    @test pointer(A) == pointer(S)
    for i in 1:prod(sz)
        @test pointer(A, i) == pointer(S, i)
        @test A[i] == S[i]
    end
    for idxs in ((1:sz[1], 1:sz[2], 1:sz[3]),
                 (1:sz[1], 2:2:sz[2], sz[3]:-1:1),
                 (2:2:sz[1]-1, sz[2]:-1:1, sz[3]:-2:2),
                 (sz[1]:-1:1, sz[2]:-1:1, sz[3]:-1:1),
                 (sz[1]-1:-3:1, sz[2]:-2:3, 1:sz[3]),)
        Ai = A[idxs...]
        Av = view(A, idxs...)
        Sv = view(S, idxs...)
        Ss = Strider{Int, 3}(vec(A), sum((first.(idxs).-1).*strides(A))+1, strides(Av), length.(idxs))
        @test pointer(Av) == pointer(Sv) == pointer(Ss)
        for i in 1:length(Av)
            @test pointer(Av, i) == pointer(Sv, i) == pointer(Ss, i)
            @test Ai[i] == Av[i] == Sv[i] == Ss[i]
        end
        for perm in ((3, 2, 1), (2, 1, 3), (3, 1, 2))
            P = permutedims(A, perm)
            Ap = Base.PermutedDimsArray(A, perm)
            Sp = Base.PermutedDimsArray(S, perm)
            Ps = Strider{Int, 3}(vec(A), 1, strides(A)[collect(perm)], sz[collect(perm)])
            @test pointer(Ap) == pointer(Sp) == pointer(Ps)
            for i in 1:length(Ap)
                # This is intentionally disabled due to ambiguity. See `Base.pointer(A::PermutedDimsArray, i::Integer)`.
                # But only evaluate one iteration as broken to reduce test report noise
                i == 1 && @test_broken pointer(Ap, i) == pointer(Sp, i) == pointer(Ps, i)
                @test P[i] == Ap[i] == Sp[i] == Ps[i]
            end
            Pv = view(P, idxs[collect(perm)]...)
            Pi = P[idxs[collect(perm)]...]
            Apv = view(Ap, idxs[collect(perm)]...)
            Spv = view(Sp, idxs[collect(perm)]...)
            Pvs = Strider{Int, 3}(vec(A), sum((first.(idxs).-1).*strides(A))+1, strides(Apv), size(Apv))
            @test pointer(Apv) == pointer(Spv) == pointer(Pvs)
            for i in 1:length(Apv)
                @test pointer(Apv, i) == pointer(Spv, i) == pointer(Pvs, i)
                @test Pi[i] == Pv[i] == Apv[i] == Spv[i] == Pvs[i]
            end
            Vp = permutedims(Av, perm)
            Ip = permutedims(Ai, perm)
            Avp = Base.PermutedDimsArray(Av, perm)
            Svp = Base.PermutedDimsArray(Sv, perm)
            @test pointer(Avp) == pointer(Svp)
            for i in 1:length(Avp)
                # This is intentionally disabled due to ambiguity. See `Base.pointer(A::PermutedDimsArray, i::Integer)`
                # But only evaluate one iteration as broken to reduce test report noise
                i == 1 && @test_broken pointer(Avp, i) == pointer(Svp, i)
                @test Ip[i] == Vp[i] == Avp[i] == Svp[i]
            end
        end
    end
end

@testset "simple 2d strided views, permutes, transposes" for sz in ((5, 3), (7, 11))
    A = collect(reshape(1:prod(sz), sz))
    S = Strider(vec(A), strides(A), sz)
    @test pointer(A) == pointer(S)
    for i in 1:prod(sz)
        @test pointer(A, i) == pointer(S, i)
        @test A[i] == S[i]
    end
    for idxs in ((1:sz[1], 1:sz[2]),
                 (1:sz[1], 2:2:sz[2]),
                 (2:2:sz[1]-1, sz[2]:-1:1),
                 (sz[1]:-1:1, sz[2]:-1:1),
                 (sz[1]-1:-3:1, sz[2]:-2:3),)
        Av = view(A, idxs...)
        Sv = view(S, idxs...)
        Ss = Strider{Int, 2}(vec(A), sum((first.(idxs).-1).*strides(A))+1, strides(Av), length.(idxs))
        @test pointer(Av) == pointer(Sv) == pointer(Ss)
        for i in 1:length(Av)
            @test pointer(Av, i) == pointer(Sv, i) == pointer(Ss, i)
            @test Av[i] == Sv[i] == Ss[i]
        end
        perm = (2, 1)
        P = permutedims(A, perm)
        Ap = Base.PermutedDimsArray(A, perm)
        At = transpose(A)
        Aa = adjoint(A)
        St = transpose(A)
        Sa = adjoint(A)
        Sp = Base.PermutedDimsArray(S, perm)
        Ps = Strider{Int, 2}(vec(A), 1, strides(A)[collect(perm)], sz[collect(perm)])
        @test pointer(Ap) == pointer(Sp) == pointer(Ps) == pointer(At) == pointer(Aa)
        for i in 1:length(Ap)
            # This is intentionally disabled due to ambiguity. See `Base.pointer(A::PermutedDimsArray, i::Integer)`
            # But only evaluate one iteration as broken to reduce test report noise
            i == 1 && @test_broken pointer(Ap, i) == pointer(Sp, i) == pointer(Ps, i) == pointer(At, i) == pointer(Aa, i) == pointer(St, i) == pointer(Sa, i)
            @test pointer(Ps, i) == pointer(At, i) == pointer(Aa, i) == pointer(St, i) == pointer(Sa, i)
            @test P[i] == Ap[i] == Sp[i] == Ps[i] == At[i] == Aa[i] == St[i] == Sa[i]
        end
        Pv = view(P, idxs[collect(perm)]...)
        Apv = view(Ap, idxs[collect(perm)]...)
        Atv = view(At, idxs[collect(perm)]...)
        Ata = view(Aa, idxs[collect(perm)]...)
        Stv = view(St, idxs[collect(perm)]...)
        Sta = view(Sa, idxs[collect(perm)]...)
        Spv = view(Sp, idxs[collect(perm)]...)
        Pvs = Strider{Int, 2}(vec(A), sum((first.(idxs).-1).*strides(A))+1, strides(Apv), size(Apv))
        @test pointer(Apv) == pointer(Spv) == pointer(Pvs) == pointer(Atv) == pointer(Ata)
        for i in 1:length(Apv)
            @test pointer(Apv, i) == pointer(Spv, i) == pointer(Pvs, i) == pointer(Atv, i) == pointer(Ata, i) == pointer(Stv, i) == pointer(Sta, i)
            @test Pv[i] == Apv[i] == Spv[i] == Pvs[i] == Atv[i] == Ata[i] == Stv[i] == Sta[i]
        end
        Vp = permutedims(Av, perm)
        Avp = Base.PermutedDimsArray(Av, perm)
        Avt = transpose(Av)
        Ava = adjoint(Av)
        Svt = transpose(Sv)
        Sva = adjoint(Sv)
        Svp = Base.PermutedDimsArray(Sv, perm)
        @test pointer(Avp) == pointer(Svp) == pointer(Avt) == pointer(Ava)
        for i in 1:length(Avp)
            # This is intentionally disabled due to ambiguity. See `Base.pointer(A::PermutedDimsArray, i::Integer)`
            # But only evaluate one iteration as broken to reduce test report noise
            i == 1 && @test_broken pointer(Avp, i) == pointer(Svp, i) == pointer(Avt, i) == pointer(Ava, i) == pointer(Svt, i) == pointer(Sva, i)
            @test pointer(Avt, i) == pointer(Ava, i) == pointer(Svt, i) == pointer(Sva, i)
            @test Vp[i] == Avp[i] == Svp[i] == Avt[i] == Ava[i] == Svt[i] == Sva[i]
        end
    end
end

@testset "first/last n elements of $(typeof(itr))" for itr in (collect(1:9),
                                                               [1 4 7; 2 5 8; 3 6 9],
                                                               ntuple(identity, 9))
    @test first(itr, 6) == [itr[1:6]...]
    @test first(itr, 25) == [itr[:]...]
    @test first(itr, 25) !== itr
    @test first(itr, 1) == [itr[1]]
    @test_throws ArgumentError first(itr, -6)
    @test last(itr, 6) == [itr[end-5:end]...]
    @test last(itr, 25) == [itr[:]...]
    @test last(itr, 25) !== itr
    @test last(itr, 1) == [itr[end]]
    @test_throws ArgumentError last(itr, -6)

    @testset "overflow (issue #45842)" begin
        @test_throws OverflowError first(typemin(Int):typemax(Int), 10)
        @test first(2:typemax(Int)-1, typemax(Int)÷2) === 2:((typemax(Int)÷2) + 1)
        @test last(2:typemax(Int), typemax(Int)÷2) ===
            range(stop=typemax(Int), length=typemax(Int)÷2)
    end
end

@testset "Base.rest" begin
    a = reshape(1:4, 2, 2)'
    @test Base.rest(a) == a[:]
    _, st = iterate(a)
    @test Base.rest(a, st) == [3, 2, 4]
end

@testset "issue #37741, non-int cat" begin
    @test [1; 1:BigInt(5)] == [1; 1:5]
    @test [1:BigInt(5); 1] == [1:5; 1]
end

@testset "Base.isstored" begin
    a = rand(3, 4, 5)
    @test Base.isstored(a, 1, 2, 3)
    @test_throws BoundsError Base.isstored(a, 4, 4, 5)
    @test_throws BoundsError Base.isstored(a, 3, 5, 5)
    @test_throws BoundsError Base.isstored(a, 3, 4, 6)
end

mutable struct TestPushArray{T, N} <: AbstractArray{T, N}
    data::Array{T}
end
Base.push!(tpa::TestPushArray{T}, a::T) where T = push!(tpa.data, a)
Base.pushfirst!(tpa::TestPushArray{T}, a::T) where T = pushfirst!(tpa.data, a)

@testset "push! and pushfirst!" begin
    a_orig = [1]
    tpa = TestPushArray{Int, 2}(a_orig)
    push!(tpa, 2, 3, 4, 5, 6)
    @test tpa.data == collect(1:6)
    a_orig = [1]
    tpa = TestPushArray{Int, 2}(a_orig)
    pushfirst!(tpa, 6, 5, 4, 3, 2)
    @test tpa.data == reverse(collect(1:6))
end

mutable struct SimpleArray{T} <: AbstractVector{T}
    els::Vector{T}
end
Base.size(sa::SimpleArray) = size(sa.els)
Base.getindex(sa::SimpleArray, idx...) = getindex(sa.els, idx...)
Base.setindex!(sa::SimpleArray, v, idx...) = setindex!(sa.els, v, idx...)
Base.resize!(sa::SimpleArray, n) = resize!(sa.els, n)
Base.copy(sa::SimpleArray) = SimpleArray(copy(sa.els))

isdefined(Main, :OffsetArrays) || @eval Main include("testhelpers/OffsetArrays.jl")
using .Main.OffsetArrays

@testset "Failing `$f` should not grow the array $a" for
        f in (push!, append!, pushfirst!, prepend!),
        a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1))
    for args in ((1,), (1,2), ([1], [2]), [1])
        orig = copy(a)
        @test_throws Exception f(a, args...)
        @test a == orig
    end
end

@testset "splatting into hvcat" begin
    t = (1, 2)
    @test [t...; 3 4] == [1 2; 3 4]
    @test [0 t...; t... 0] == [0 1 2; 1 2 0]
    @test_throws ArgumentError [t...; 3 4 5]

    @test Int[t...; 3 4] == [1 2; 3 4]
    @test Int[0 t...; t... 0] == [0 1 2; 1 2 0]
    @test_throws DimensionMismatch Int[t...; 3 4 5]
end

@testset "issue #39896, modified getindex " begin
    for arr = ([1:10;], reshape([1.0:16.0;],4,4), reshape(['a':'h';],2,2,2))
        for inds = (2:5, Base.OneTo(5), BigInt(3):BigInt(5), UInt(4):UInt(3),
            Base.IdentityUnitRange(Base.OneTo(4)))
            @test arr[inds] == arr[collect(inds)]
            @test arr[inds] isa AbstractVector{eltype(arr)}
        end
    end
    # Test that ranges and arrays behave identically for indices with 1-based axes
    for r in (1:10, 1:1:10, Base.OneTo(10),
        Base.IdentityUnitRange(Base.OneTo(10)), Base.IdentityUnitRange(1:10))
        for inds = (2:5, Base.OneTo(5), BigInt(3):BigInt(5), UInt(4):UInt(3),
            Base.IdentityUnitRange(Base.OneTo(4)))
            @test r[inds] == r[collect(inds)] == collect(r)[inds] == collect(r)[collect(inds)]
        end
    end
    for arr = ([1], reshape([1.0],1,1), reshape(['a'],1,1,1))
        @test arr[true:true] == [arr[1]]
        @test arr[true:true] isa AbstractVector{eltype(arr)}
        @test arr[false:false] == []
        @test arr[false:false] isa AbstractVector{eltype(arr)}
    end
    for arr = ([1:10;], reshape([1.0:16.0;],4,4), reshape(['a':'h';],2,2,2))
        @test_throws BoundsError arr[true:true]
        @test_throws BoundsError arr[false:false]
    end
end

using Base: typed_hvncat
@testset "hvncat" begin
    a = fill(1, (2,3,2,4,5))
    b = fill(2, (1,1,2,4,5))
    c = fill(3, (1,2,2,4,5))
    d = fill(4, (1,1,1,4,5))
    e = fill(5, (1,1,1,4,5))
    f = fill(6, (1,1,1,4,5))
    g = fill(7, (2,3,1,4,5))
    h = fill(8, (3,3,3,1,2))
    i = fill(9, (3,2,3,3,2))
    j = fill(10, (3,1,3,3,2))

    result = [a; b c ;;; d e f ; g ;;;;; h ;;;; i j]
    @test size(result) == (3,3,3,4,7)
    @test result == [a; [b ;; c] ;;; [d e f] ; g ;;;;; h ;;;; i ;; j]
    @test result == cat(cat([a ; b c], [d e f ; g], dims = 3), cat(h, [i j], dims = 4), dims = 5)

    # terminating semicolons extend dimensions
    @test [1;] == [1]
    @test [1;;] == fill(1, (1,1))

    for v in (1, fill(1), fill(1,1,1), fill(1, 1, 1, 1))
        @test_throws DimensionMismatch [v; v;; v]
        @test_throws DimensionMismatch [v; v;; v; v; v]
        @test_throws DimensionMismatch [v; v; v;; v; v]
        @test_throws DimensionMismatch [v; v;; v; v;;; v; v;; v; v;; v; v]
        @test_throws DimensionMismatch [v; v;; v; v;;; v; v]
        @test_throws DimensionMismatch [v; v;; v; v;;; v; v; v;; v; v]
        @test_throws DimensionMismatch [v; v;; v; v;;; v; v;; v; v; v]
        # ensure a wrong shape with the right number of elements doesn't pass through
        @test_throws DimensionMismatch [v; v;; v; v;;; v; v; v; v]

        @test [v; v;; v; v] == fill(1, ndims(v) == 3 ? (2, 2, 1) : (2,2))
        @test [v; v;; v; v;;;] == fill(1, 2, 2, 1)
        @test [v; v;; v; v] == fill(1, ndims(v) == 3 ? (2, 2, 1) : (2,2))
        @test [v v; v v;;;] == fill(1, 2, 2, 1)
        @test [v; v;; v; v;;; v; v;; v; v;;] == fill(1, 2, 2, 2)
        @test [v; v; v;; v; v; v;;; v; v; v;; v; v; v;;] == fill(1, 3, 2, 2)
        @test [v v; v v;;; v v; v v] == fill(1, 2, 2, 2)
        @test [v v v; v v v;;; v v v; v v v] == fill(1, 2, 3, 2)
    end

    # mixed scalars and arrays work, for numbers and strings
    for v = (1, "test")
        @test [v v;;; fill(v, 1, 2)] == fill(v, 1, 2, 2)
    end

    # output dimensions are maximum of input dimensions and concatenation dimension
    begin
        v1 = fill(1, 1, 1)
        v2 = fill(1, 1, 1, 1, 1)
        v3 = fill(1, 1, 2, 1, 1)
        @test [v1 ;;; v2] == [1 ;;; 1 ;;;;]
        @test [v2 ;;; v1] == [1 ;;; 1 ;;;;]
        @test [v3 ;;; v1 v1] == [1 1 ;;; 1 1 ;;;;]
        @test [v1 v1 ;;; v3] == [1 1 ;;; 1 1 ;;;;]
        @test [v2 v1 ;;; v1 v1] == [1 1 ;;; 1 1 ;;;;]
        @test [v1 v1 ;;; v1 v2] == [1 1 ;;; 1 1 ;;;;]
        @test [v2 ;;; 1] == [1 ;;; 1 ;;;;]
        @test [1 ;;; v2] == [1 ;;; 1 ;;;;]
        @test [v3 ;;; 1 v1] == [1 1 ;;; 1 1 ;;;;]
        @test [v1 1 ;;; v3] == [1 1 ;;; 1 1 ;;;;]
        @test [v2 1 ;;; v1 v1] == [1 1 ;;; 1 1 ;;;;]
        @test [v1 1 ;;; v1 v2] == [1 1 ;;; 1 1 ;;;;]
    end

    # dims form
    for v ∈ ((), (1,), ([1],), (1, [1]), ([1], 1), ([1], [1]))
        # reject dimension < 0
        @test_throws ArgumentError hvncat(-1, v...)

        # reject shape tuple with no elements
        @test_throws ArgumentError hvncat(((),), true, v...)
    end

    # reject dims or shape with negative or zero values
    for v1 ∈ (-1, 0, 1)
        for v2 ∈ (-1, 0, 1)
            v1 == v2 == 1 && continue
            for v3 ∈ ((), (1,), ([1],), (1, [1]), ([1], 1), ([1], [1]))
                @test_throws ArgumentError hvncat((v1, v2), true, v3...)
                @test_throws str->(occursin("`shape` argument must consist of positive integers", str) ||
                                   occursin("reducing over an empty collection is not allowed", str)) hvncat(((v1,), (v2,)), true, v3...)
            end
        end
    end

    for v ∈ ((1, [1]), ([1], 1), ([1], [1]))
        # reject shape with more than one end value
        @test_throws ArgumentError hvncat(((1, 1),), true, v...)
    end

    for v ∈ ((1, 2, 3), (1, 2, [3]), ([1], [2], [3]))
        # reject shape with more values in later level
        @test_throws ArgumentError hvncat(((2, 1), (1, 1, 1)), true, v...)
    end

    # reject shapes that don't nest evenly between levels (e.g. 1 + 2 does not fit into 2)
    @test_throws DimensionMismatch hvncat(((1, 2, 1), (2, 2), (4,)), true, [1 2], [3], [4], [1 2; 3 4])

    # zero-length arrays are handled appropriately
    @test [zeros(Int, 1, 2, 0) ;;; 1 3] == [1 3;;;]
    @test [[] ;;; [] ;;; []] == Array{Any}(undef, 0, 1, 3)
    @test [[] ; 1 ;;; 2 ; []] == [1 ;;; 2]
    @test [[] ; [] ;;; [] ; []] == Array{Any}(undef, 0, 1, 2)
    @test [[] ; 1 ;;; 2] == [1 ;;; 2]
    @test [[] ; [] ;;; [] ;;; []] == Array{Any}(undef, 0, 1, 3)
    z = zeros(Int, 0, 0, 0)
    [z z ; z ;;; z ;;; z] == Array{Int}(undef, 0, 0, 0)

    for v1 ∈ (zeros(Int, 0, 0), zeros(Int, 0, 0, 0, 0), zeros(Int, 0, 0, 0, 0, 0, 0, 0))
        for v2 ∈ (1, [1])
            for v3 ∈ (2, [2])
                @test_throws DimensionMismatch [v1 ;;; v2]
                @test_throws DimensionMismatch [v1 ;;; v2 v3]
                @test_throws DimensionMismatch [v1 v1 ;;; v2 v3]
            end
        end
    end
    v1 = zeros(Int, 0, 0, 0)
    for v2 ∈ (1, [1])
        for v3 ∈ (2, [2])
            @test_throws DimensionMismatch [v1 ;;; v2 v3]
            @test_throws DimensionMismatch [v1 ;;; v2]
            @test_throws DimensionMismatch [v1 v1 ;;; v2 v3]
        end
    end

    # 0-dimension behaviors
    # exactly one argument, placed in an array
    # if already an array, copy, with type conversion as necessary
    @test_throws ArgumentError hvncat(0)
    @test hvncat(0, 1) == fill(1)
    @test hvncat(0, [1]) == [1]
    @test_throws ArgumentError hvncat(0, 1, 1)
    @test_throws ArgumentError typed_hvncat(Float64, 0)
    @test typed_hvncat(Float64, 0, 1) == fill(1.0)
    @test typed_hvncat(Float64, 0, [1]) == Float64[1.0]
    @test_throws ArgumentError typed_hvncat(Float64, 0, 1, 1)
    @test_throws ArgumentError hvncat((), true) == []
    @test hvncat((), true, 1) == fill(1)
    @test hvncat((), true, [1]) == [1]
    @test_throws ArgumentError hvncat((), true, 1, 1)
    @test_throws ArgumentError typed_hvncat(Float64, (), true) == Float64[]
    @test typed_hvncat(Float64, (), true, 1) == fill(1.0)
    @test typed_hvncat(Float64, (), true, [1]) == [1.0]
    @test_throws ArgumentError typed_hvncat(Float64, (), true, 1, 1)

    # 1-dimension behaviors
    # int form
    @test hvncat(1) == []
    @test hvncat(1, 1) == [1]
    @test hvncat(1, [1]) == [1]
    @test hvncat(1, [1 2; 3 4]) == [1 2; 3 4]
    @test hvncat(1, 1, 1) == [1 ; 1]
    @test typed_hvncat(Float64, 1) == Float64[]
    @test typed_hvncat(Float64, 1, 1) == Float64[1.0]
    @test typed_hvncat(Float64, 1, [1]) == Float64[1.0]
    @test typed_hvncat(Float64, 1, 1, 1) == Float64[1.0 ; 1.0]
    # dims form
    @test_throws ArgumentError hvncat((1,), true)
    @test hvncat((2,), true, 1, 1) == [1; 1]
    @test hvncat((2,), true, [1], [1]) == [1; 1]
    @test_throws ArgumentError hvncat((2,), true, 1)
    @test typed_hvncat(Float64, (2,), true, 1, 1) == Float64[1.0; 1.0]
    @test typed_hvncat(Float64, (2,), true, [1], [1]) == Float64[1.0; 1.0]
    @test_throws ArgumentError typed_hvncat(Float64, (2,), true, 1)
    # row_first has no effect with just one dimension of the dims form
    @test hvncat((2,), false, 1, 1) == [1; 1]
    @test typed_hvncat(Float64, (2,), false, 1, 1) == Float64[1.0; 1.0]
    # shape form
    @test hvncat(((2,),), true, 1, 1) == [1 1]
    @test hvncat(((2,),), true, [1], [1]) == [1 1]
    @test_throws ArgumentError hvncat(((2,),), true, 1)
    @test hvncat(((2,),), false, 1, 1) == [1; 1]
    @test hvncat(((2,),), false, [1], [1]) == [1; 1]
    @test typed_hvncat(Float64, ((2,),), true, 1, 1) == Float64[1.0 1.0]
    @test typed_hvncat(Float64, ((2,),), true, [1], [1]) == Float64[1.0 1.0]
    @test_throws ArgumentError typed_hvncat(Float64, ((2,),), true, 1)
    @test typed_hvncat(Float64, ((2,),), false, 1, 1) == Float64[1.0; 1.0]
    @test typed_hvncat(Float64, ((2,),), false, [1], [1]) == Float64[1.0; 1.0]

    # zero-value behaviors for int form above dimension zero
    # e.g. [;;], [;;;], though that isn't valid syntax
    @test [] == hvncat(1) isa Array{Any, 1}
    @test Array{Any, 2}(undef, 0, 0) == hvncat(2) isa Array{Any, 2}
    @test Array{Any, 3}(undef, 0, 0, 0) == hvncat(3) isa Array{Any, 3}
    @test Int[] == typed_hvncat(Int, 1) isa Array{Int, 1}
    @test Array{Int, 2}(undef, 0, 0) == typed_hvncat(Int, 2) isa Array{Int, 2}
    @test Array{Int, 3}(undef, 0, 0, 0) == typed_hvncat(Int, 3) isa Array{Int, 3}

    # Issue 43933 - semicolon precedence mistake should produce an error
    @test_throws DimensionMismatch [[1 1]; 2 ;; 3 ; [3 4]]
    @test_throws DimensionMismatch [[1 ;;; 1]; 2 ;;; 3 ; [3 ;;; 4]]

    @test [[1 2; 3 4] [5; 6]; [7 8] 9;;;] == [1 2 5; 3 4 6; 7 8 9;;;]

    #45461, #46133 - ensure non-numeric types do not error
    @test [1;;; 2;;; nothing;;; 4] == reshape([1; 2; nothing; 4], (1, 1, 4))
    @test [1 2;;; nothing 4] == reshape([1; 2; nothing; 4], (1, 2, 2))
    @test [[1 2];;; nothing 4] == reshape([1; 2; nothing; 4], (1, 2, 2))
    @test ["A";;"B";;"C";;"D"] == ["A" "B" "C" "D"]
    @test ["A";"B";;"C";"D"] == ["A" "C"; "B" "D"]
    @test [["A";"B"];;"C";"D"] == ["A" "C"; "B" "D"]
end

@testset "stack" begin
    # Basics
    for args in ([[1, 2]], [1:2, 3:4], [[1 2; 3 4], [5 6; 7 8]],
                AbstractVector[1:2, [3.5, 4.5]], Vector[[1,2], [3im, 4im]],
                [[1:2, 3:4], [5:6, 7:8]], [fill(1), fill(2)])
        X = stack(args)
        Y = cat(args...; dims=ndims(args[1])+1)
        @test X == Y
        @test typeof(X) === typeof(Y)

        X2 = stack(x for x in args)
        @test X2 == Y
        @test typeof(X2) === typeof(Y)

        X3 = stack(x for x in args if true)
        @test X3 == Y
        @test typeof(X3) === typeof(Y)

        if isconcretetype(eltype(args))
            @inferred stack(args)
            @inferred stack(x for x in args)
        end
    end

    # Higher dims
    @test size(stack([rand(2,3) for _ in 1:4, _ in 1:5])) == (2,3,4,5)
    @test size(stack(rand(2,3) for _ in 1:4, _ in 1:5)) == (2,3,4,5)
    @test size(stack(rand(2,3) for _ in 1:4, _ in 1:5 if true)) == (2, 3, 20)
    @test size(stack([rand(2,3) for _ in 1:4, _ in 1:5]; dims=1)) == (20, 2, 3)
    @test size(stack(rand(2,3) for _ in 1:4, _ in 1:5; dims=2)) == (2, 20, 3)

    # Tuples
    @test stack([(1,2), (3,4)]) == [1 3; 2 4]
    @test stack(((1,2), (3,4))) == [1 3; 2 4]
    @test stack(Any[(1,2), (3,4)]) == [1 3; 2 4]
    @test stack([(1,2), (3,4)]; dims=1) == [1 2; 3 4]
    @test stack(((1,2), (3,4)); dims=1) == [1 2; 3 4]
    @test stack(Any[(1,2), (3,4)]; dims=1) == [1 2; 3 4]
    @test size(@inferred stack(Iterators.product(1:3, 1:4))) == (2,3,4)
    @test @inferred(stack([('a', 'b'), ('c', 'd')])) == ['a' 'c'; 'b' 'd']
    @test @inferred(stack([(1,2+3im), (4, 5+6im)])) isa Matrix{Number}

    # stack(f, iter)
    @test @inferred(stack(x -> [x, 2x], 3:5)) == [3 4 5; 6 8 10]
    @test @inferred(stack(x -> x*x'/2, [1:2, 3:4])) == [0.5 1.0; 1.0 2.0;;; 4.5 6.0; 6.0 8.0]
    @test @inferred(stack(*, [1:2, 3:4], 5:6)) == [5 18; 10 24]

    # Iterators
    @test stack([(a=1,b=2), (a=3,b=4)]) == [1 3; 2 4]
    @test stack([(a=1,b=2), (c=3,d=4)]) == [1 3; 2 4]
    @test stack([(a=1,b=2), (c=3,d=4)]; dims=1) == [1 2; 3 4]
    @test stack([(a=1,b=2), (c=3,d=4)]; dims=2) == [1 3; 2 4]
    @test stack((x/y for x in 1:3) for y in 4:5) == (1:3) ./ (4:5)'
    @test stack((x/y for x in 1:3) for y in 4:5; dims=1) == (1:3)' ./ (4:5)

    # Exotic
    ips = ((Iterators.product([i,i^2], [2i,3i,4i], 1:4)) for i in 1:5)
    @test size(stack(ips)) == (2, 3, 4, 5)
    @test stack(ips) == cat(collect.(ips)...; dims=4)
    ips_cat2 = cat(reshape.(collect.(ips), Ref((2,1,3,4)))...; dims=2)
    @test stack(ips; dims=2) == ips_cat2
    @test stack(collect.(ips); dims=2) == ips_cat2
    ips_cat3 = cat(reshape.(collect.(ips), Ref((2,3,1,4)))...; dims=3)
    @test stack(ips; dims=3) == ips_cat3  # path for non-array accumulation on non-final dims
    @test stack(collect, ips; dims=3) == ips_cat3  # ... and for array accumulation
    @test stack(collect.(ips); dims=3) == ips_cat3

    # Trivial, because numbers are iterable:
    @test stack(abs2, 1:3) == [1, 4, 9] == collect(Iterators.flatten(abs2(x) for x in 1:3))

    # Allocation tests
    xv = [rand(10) for _ in 1:100]
    xt = Tuple.(xv)
    for dims in (1, 2, :)
        @test stack(xv; dims) == stack(xt; dims)
        @test_skip 9000 > @allocated stack(xv; dims)
        @test_skip 9000 > @allocated stack(xt; dims)
    end
    xr = (reshape(1:1000,10,10,10) for _ = 1:1000)
    for dims in (1, 2, 3, :)
        stack(xr; dims)
        @test_skip 8.1e6 > @allocated stack(xr; dims)
    end

    # Mismatched sizes
    @test_throws DimensionMismatch stack([1:2, 1:3])
    @test_throws DimensionMismatch stack([1:2, 1:3]; dims=1)
    @test_throws DimensionMismatch stack([1:2, 1:3]; dims=2)
    @test_throws DimensionMismatch stack([(1,2), (3,4,5)])
    @test_throws DimensionMismatch stack([(1,2), (3,4,5)]; dims=1)
    @test_throws DimensionMismatch stack(x for x in [1:2, 1:3])
    @test_throws DimensionMismatch stack([[5 6; 7 8], [1, 2, 3, 4]])
    @test_throws DimensionMismatch stack([[5 6; 7 8], [1, 2, 3, 4]]; dims=1)
    @test_throws DimensionMismatch stack(x for x in [[5 6; 7 8], [1, 2, 3, 4]])
    # Inner iterator of unknown length
    @test_throws MethodError stack((x for x in 1:3 if true) for _ in 1:4)
    @test_throws MethodError stack((x for x in 1:3 if true) for _ in 1:4; dims=1)

    @test_throws ArgumentError stack([1:3, 4:6]; dims=0)
    @test_throws ArgumentError stack([1:3, 4:6]; dims=3)
    @test_throws ArgumentError stack(abs2, 1:3; dims=2)

    # Empty
    @test_throws ArgumentError stack(())
    @test_throws ArgumentError stack([])
    @test_throws ArgumentError stack(x for x in 1:3 if false)
end

@testset "tests from PR 31644" begin
    v_v_same = [rand(128) for ii in 1:100]
    v_v_diff = Any[rand(128), rand(Float32,128), rand(Int, 128)]
    v_v_diff_typed = Union{Vector{Float64},Vector{Float32},Vector{Int}}[rand(128), rand(Float32,128), rand(Int, 128)]
    for v_v in (v_v_same, v_v_diff, v_v_diff_typed)
        # Cover all combinations of iterator traits.
        g_v = (x for x in v_v)
        f_g_v = Iterators.filter(x->true, g_v)
        f_v_v = Iterators.filter(x->true, v_v);
        hcat_expected = hcat(v_v...)
        vcat_expected = vcat(v_v...)
        @testset "$(typeof(data))" for data in (v_v, g_v, f_g_v, f_v_v)
            @test stack(data) == hcat_expected
            @test vec(stack(data)) == vcat_expected
        end
    end
end

@testset "keepat!" begin
    a = [1:6;]
    @test a === keepat!(a, 1:5)
    @test a == 1:5
    @test keepat!(a, [2, 4]) == [2, 4]
    @test isempty(keepat!(a, []))

    a = [1:6;]
    @test_throws BoundsError keepat!(a, 1:10) # make sure this is not a no-op
    @test_throws BoundsError keepat!(a, 2:10)
    @test_throws ArgumentError keepat!(a, [2, 4, 3])

    b = BitVector([1, 1, 1, 0, 0])
    @test b === keepat!(b, 1:5)
    @test b == [1, 1, 1, 0, 0]
    @test keepat!(b, 2:4) == [1, 1, 0]
    @test_throws BoundsError keepat!(a, -1:10)
    @test_throws ArgumentError keepat!(a, [2, 1])
    @test isempty(keepat!(a, []))
end

@testset "reshape methods for AbstractVectors" begin
    for r in Any[1:3, Base.IdentityUnitRange(3:4)]
        @test reshape(r, :) === reshape(r, (:,)) === r
    end
    r = 3:5
    rr = reshape(r, 1, 3)
    @test length(rr) == length(r)
end

module IRUtils
    include("compiler/irutils.jl")
end

function check_pointer_strides(A::AbstractArray)
    # Make sure stride(A, i) is equivalent with strides(A)[i] (if 1 <= i <= ndims(A))
    dims = ntuple(identity, ndims(A))
    map(i -> stride(A, i), dims) == @inferred(strides(A)) || return false
    # Test pointer via value check.
    first(A) === Base.unsafe_load(pointer(A)) || return false
    # Test strides via value check.
    for i in eachindex(IndexLinear(), A)
        A[i] === Base.unsafe_load(pointer(A, i)) || return false
    end
    return true
end

@testset "strides for ReshapedArray" begin
    # Type-based contiguous Check
    a = vec(reinterpret(reshape, Int16, reshape(view(reinterpret(Int32, randn(10)), 2:11), 5, :)))
    f(a) = only(strides(a));
    @test IRUtils.fully_eliminated(f, Base.typesof(a)) && f(a) == 1
    # General contiguous check
    a = view(rand(10,10), 1:10, 1:10)
    @test check_pointer_strides(vec(a))
    b = view(parent(a), 1:9, 1:10)
    @test_throws "Input is not strided." strides(vec(b))
    # StridedVector parent
    for n in 1:3
        a = view(collect(1:60n), 1:n:60n)
        @test check_pointer_strides(reshape(a, 3, 4, 5))
        @test check_pointer_strides(reshape(a, 5, 6, 2))
        b = view(parent(a), 60n:-n:1)
        @test check_pointer_strides(reshape(b, 3, 4, 5))
        @test check_pointer_strides(reshape(b, 5, 6, 2))
    end
    # StridedVector like parent
    a = randn(10, 10, 10)
    b = view(a, 1:10, 1:1, 5:5)
    @test check_pointer_strides(reshape(b, 2, 5))
    # Other StridedArray parent
    a = view(randn(10,10), 1:9, 1:10)
    @test check_pointer_strides(reshape(a,3,3,2,5))
    @test check_pointer_strides(reshape(a,3,3,5,2))
    @test check_pointer_strides(reshape(a,9,5,2))
    @test check_pointer_strides(reshape(a,3,3,10))
    @test check_pointer_strides(reshape(a,1,3,1,3,1,5,1,2))
    @test check_pointer_strides(reshape(a,3,3,5,1,1,2,1,1))
    @test_throws "Input is not strided." strides(reshape(a,3,6,5))
    @test_throws "Input is not strided." strides(reshape(a,3,2,3,5))
    @test_throws "Input is not strided." strides(reshape(a,3,5,3,2))
    @test_throws "Input is not strided." strides(reshape(a,5,3,3,2))
    # Zero dimensional parent
    struct FakeZeroDimArray <: AbstractArray{Int, 0} end
    Base.strides(::FakeZeroDimArray) = ()
    Base.size(::FakeZeroDimArray) = ()
    a = reshape(FakeZeroDimArray(),1,1,1)
    @test @inferred(strides(a)) == (1, 1, 1)
    # Dense parent (but not StridedArray)
    A = reinterpret(Int8, reinterpret(reshape, Int16, rand(Int8, 2, 3, 3)))
    @test check_pointer_strides(reshape(A, 3, 2, 3))
end

@testset "pointer for SubArray with none-dense parent." begin
    a = view(Matrix(reshape(0x01:0xc8, 20, :)), 1:2:20, :)
    b = reshape(a, 20, :)
    @test check_pointer_strides(view(b, 2:11, 1:5))
    @test check_pointer_strides(view(b, reshape(2:11, 2, :), 1:5))
end

@testset "stride for 0 dims array #44087" begin
    struct Fill44087 <: AbstractArray{Int,0}
        a::Int
    end
    # `stride` shouldn't work if `strides` is not defined.
    @test_throws MethodError stride(Fill44087(1), 1)
    # It is intentionally to only check the return type. (The value is somehow arbitrary)
    @test stride(fill(1), 1) isa Int
    @test stride(reinterpret(Float64, fill(Int64(1))), 1) isa Int
    @test stride(reinterpret(reshape, Float64, fill(Int64(1))), 1) isa Int
    @test stride(Base.ReshapedArray(fill(1), (), ()), 1) isa Int
end

@testset "to_indices inference (issue #42001 #44059)" begin
    CIdx = CartesianIndex
    CIdc = CartesianIndices
    @test (@inferred to_indices([], ntuple(Returns(CIdx(1)), 32))) == ntuple(Returns(1), 32)
    @test (@inferred to_indices([], ntuple(Returns(CIdc(1:1)), 32))) == ntuple(Returns(Base.OneTo(1)), 32)
    @test (@inferred to_indices([], (CIdx(), 1, CIdx(1,1,1)))) == ntuple(Returns(1), 4)
    A = randn(2, 2, 2, 2, 2, 2);
    i = CIdx((1, 1))
    @test (@inferred A[i,i,i]) === A[1]
    @test (@inferred to_indices([], (1, CIdx(1, 1), 1, CIdx(1, 1), 1, CIdx(1, 1), 1))) == ntuple(Returns(1), 10)
end

@testset "type-based offset axes check" begin
    a = randn(ComplexF64, 10)
    b = randn(ComplexF64, 4, 4, 4, 4)
    ta = reinterpret(Float64, a)
    tb = reinterpret(Float64, view(a, 1:2:10))
    tc = reinterpret(Float64, reshape(view(a, 1:3:10), 2, 2, 1))
    td = view(b, :, :, 1, 1)
    # Issue #44040
    @test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc))
    @test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(tc, tc))
    @test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc, tb))
    # Issue #49332
    @test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(td, td, td))
    # Ranges && CartesianIndices
    @test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(1:10, Base.OneTo(10), 1.0:2.0, LinRange(1.0, 2.0, 2), 1:2:10, CartesianIndices((1:2:10, 1:2:10))))
    # Remind us to call `any` in `Base.has_offset_axes` once our compiler is ready.
    @inline _has_offset_axes(A) = @inline any(x -> Int(first(x))::Int != 1, axes(A))
    @inline _has_offset_axes(As...) = @inline any(_has_offset_axes, As)
    a, b = zeros(2, 2, 2), zeros(2, 2)
    @test_broken IRUtils.fully_eliminated(_has_offset_axes, Base.typesof(a, a, b, b))
end

# type stable [x;;] (https://github.com/JuliaLang/julia/issues/45952)
f45952(x) = [x;;]
@inferred f45952(1.0)

@testset "isassigned with a Bool index" begin
    A = zeros(2,2)
    @test_throws "invalid index: true of type Bool" isassigned(A, 1, true)
    @test_throws "invalid index: true of type Bool" isassigned(A, true)
end

@testset "repeat for FillArrays" begin
    f = FillArrays.Fill(3, (4,))
    @test repeat(f, 2) === FillArrays.Fill(3, (8,))
    @test repeat(f, 2, 3) === FillArrays.Fill(3, (8, 3))
    @test repeat(f, inner=(1,2), outer=(3,1)) === repeat(f, 3, 2) === FillArrays.Fill(3, (12,2))
    f = FillArrays.Fill(3, (4, 2))
    @test repeat(f, 2, 3) === FillArrays.Fill(3, (8, 6))
    @test repeat(f, 2, 3, 4) === FillArrays.Fill(3, (8, 6, 4))
    @test repeat(f, inner=(1,2), outer=(3,1)) === FillArrays.Fill(3, (12, 4))
end

@testset "zero" begin
    @test zero([1 2; 3 4]) isa Matrix{Int}
    @test zero([1 2; 3 4]) == [0 0; 0 0]

    @test zero([1.0]) isa Vector{Float64}
    @test zero([1.0]) == [0.0]

    @test zero([[2,2], [3,3,3]]) isa Vector{Vector{Int}}
    @test zero([[2,2], [3,3,3]]) == [[0,0], [0, 0, 0]]


    @test zero(Union{Float64, Missing}[missing]) == [0.0]
    struct CustomNumber <: Number
        val::Float64
    end
    Base.zero(::Type{CustomNumber}) = CustomNumber(0.0)
    @test zero([CustomNumber(5.0)]) == [CustomNumber(0.0)]
    @test zero(Union{CustomNumber, Missing}[missing]) == [CustomNumber(0.0)]
    @test zero(Vector{Union{CustomNumber, Missing}}(undef, 1)) == [CustomNumber(0.0)]
end

@testset "`_prechecked_iterate` optimization" begin
    function test_prechecked_iterate(iter)
        Js = Base._prechecked_iterate(iter)
        for I in iter
            J, s = Js::NTuple{2,Any}
            @test J === I
            Js = Base._prechecked_iterate(iter, s)
        end
    end
    test_prechecked_iterate(1:10)
    test_prechecked_iterate(Base.OneTo(10))
    test_prechecked_iterate(CartesianIndices((3, 3)))
    test_prechecked_iterate(CartesianIndices(()))
    test_prechecked_iterate(LinearIndices((3, 3)))
    test_prechecked_iterate(LinearIndices(()))
    test_prechecked_iterate(Base.SCartesianIndices2{3}(1:3))
end

@testset "IndexStyles in copyto!" begin
    A = rand(3,2)
    B = zeros(size(A))
    colons = ntuple(_->:, ndims(B))
    # Ensure that the AbstractArray methods are hit
    # by using views instead of Arrays
    @testset "IndexLinear - IndexLinear" begin
        B .= 0
        copyto!(view(B, colons...), A)
        @test B == A
    end
    @testset "IndexLinear - IndexCartesian" begin
        B .= 0
        copyto!(view(B, colons...), view(A, axes(A)...))
        @test B == A
    end
    @testset "IndexCartesian - IndexLinear" begin
        B .= 0
        copyto!(view(B, axes(B)...), A)
        @test B == A
    end
    @testset "IndexCartesian - IndexCartesian" begin
        B .= 0
        copyto!(view(B, axes(B)...), view(A, axes(A)...))
        @test B == A
    end
end

@testset "_unsetindex!" begin
    struct MyMatrixUnsetIndexCartInds{T,A<:AbstractMatrix{T}} <: AbstractMatrix{T}
        data :: A
    end
    Base.size(A::MyMatrixUnsetIndexCartInds) = size(A.data)
    Base.getindex(M::MyMatrixUnsetIndexCartInds, i::Int, j::Int) = M.data[i,j]
    Base.setindex!(M::MyMatrixUnsetIndexCartInds, v, i::Int, j::Int) = setindex!(M.data, v, i, j)
    struct MyMatrixUnsetIndexLinInds{T,A<:AbstractMatrix{T}} <: AbstractMatrix{T}
        data :: A
    end
    Base.size(A::MyMatrixUnsetIndexLinInds) = size(A.data)
    Base.getindex(M::MyMatrixUnsetIndexLinInds, i::Int) = M.data[i]
    Base.setindex!(M::MyMatrixUnsetIndexLinInds, v, i::Int) = setindex!(M.data, v, i)
    Base.IndexStyle(::Type{<:MyMatrixUnsetIndexLinInds}) = IndexLinear()

    function test_unsetindex(MT)
        M = MT(ones(2,2))
        M2 = MT(Matrix{BigFloat}(undef, 2,2))
        copyto!(M, M2)
        @test all(==(1), M)
        M3 = MT(Matrix{BigFloat}(undef, 2,2))
        for i in eachindex(M3)
            @test !isassigned(M3, i)
        end
        M3 .= 1
        @test_throws MethodError copyto!(M3, M2)
    end
    test_unsetindex(MyMatrixUnsetIndexCartInds)
    test_unsetindex(MyMatrixUnsetIndexLinInds)
end

@testset "reshape for offset arrays" begin
    p = Base.IdentityUnitRange(3:4)
    r = reshape(p, :, 1)
    @test r[eachindex(r)] == UnitRange(p)
    @test collect(r) == r

    struct ZeroBasedArray{T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
        a :: A
        function ZeroBasedArray(a::AbstractArray)
            Base.require_one_based_indexing(a)
            new{eltype(a), ndims(a), typeof(a)}(a)
        end
    end
    Base.parent(z::ZeroBasedArray) = z.a
    Base.size(z::ZeroBasedArray) = size(parent(z))
    Base.axes(z::ZeroBasedArray) = map(x -> Base.IdentityUnitRange(0:x - 1), size(parent(z)))
    Base.getindex(z::ZeroBasedArray{<:Any, N}, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...]
    Base.setindex!(z::ZeroBasedArray{<:Any, N}, val, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...] = val

    z = ZeroBasedArray(collect(1:4))
    r2 = reshape(z, :, 1)
    @test r2[CartesianIndices(r2)] == r2[LinearIndices(r2)]
    r2[firstindex(r2)] = 34
    @test z[0] == 34
    r2[eachindex(r2)] = r2 .* 2
    for (i, j) in zip(eachindex(r2), eachindex(z))
        @test r2[i] == z[j]
    end
end
back to top