ronantakizawa/codereview-bench huggingface dataset:
Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix{T}, uplo=:U) where {T} =
    hermitianpart!(copyto!(similar(A, typeof(one(T) / 2)), A), uplo)
hermitianpart(x::Number) = real(x)

"""
    hermitianpart!(A, uplo=:U)

Overwrite the square matrix `A` with its Hermitian part, `(A + A') / 2`,
and return `Hermitian(A, uplo)`.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) =
    Hermitian(_hermorsympart!(hermitianpart, adjoint, A, char_uplo(uplo)), uplo)

function _hermorsympart!(real::Function, conj::Function, A::AbstractMatrix, uplo::Char)
    require_one_based_indexing(A)
    n = checksquare(A)
    triangle = uplo === 'U' ? (j -> 1:(j - 1)) : (j -> (j + 1):n)
    @inbounds for j in 1:n
        A[j, j] = real(A[j, j])
        for i in triangle(j)
            A[i, j] = (A[i, j] + conj(A[j, i])) / 2
        end
    end
    return A
end


Review comment (suggestion):
```suggestion
    @inbounds for j in 1:n
        A[j, j] = real(A[j, j])
        for i in (uplo === 'U' ? (1:(j - 1)) : ((j + 1):n))
```

Code after:
of `A`; it is also sometimes called the "operator real part". The optional argument `uplo` controls the corresponding argument of the
[`Hermitian`](@ref) view. For real matrices, the latter is equivalent to a
[`Symmetric`](@ref) view.

See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref) for the corresponding out-of-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::Number) = real(a)

function _hermitianpart!(A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end
Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Symmetric and Hermitian matrices
struct Symmetric{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
    data::S
    uplo::Char

    function Symmetric{T,S}(data, uplo) where {T,S<:AbstractMatrix{<:T}}
        require_one_based_indexing(data)
        (uplo != 'U' && uplo != 'L') && throw_uplo()
        new{T,S}(data, uplo)
    end
end
"""
    Symmetric(A, uplo=:U)

Construct a `Symmetric` view of the upper (if `uplo = :U`) or lower (if `uplo = :L`)
triangle of the matrix `A`.

`Symmetric` views are mainly useful for real-symmetric matrices, for which
specialized algorithms (e.g. for eigenproblems) are enabled for `Symmetric` types.
More generally, see also `Hermitian(A)` for Hermitian matrices `A == A'`, which 
is effectively equivalent to `Symmetric` for real matrices but is also useful for
complex matrices.  (Whereas complex `Symmetric` matrices are supported but have few
if any specialized algorithms.)

To compute the symmetric part of a real matrix, or more generally the Hermitian part `(A + A') / 2` of
a real or complex matrix `A`, use [`hermitianpart`](@ref).

# Examples
```jldoctest
julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Matrix{Int64}:
 1  2  3
 4  5  6
 7  8  9

julia> Supper = Symmetric(A)
3×3 Symmetric{Int64, Matrix{Int64}}:
 1  2  3
 2  5  6
 3  6  9

julia> Slower = Symmetric(A, :L)
3×3 Symmetric{Int64, Matrix{Int64}}:
 1  4  7
 4  5  8

Review comment (suggestion):
```suggestion
More generally, see also [`Hermitian(A)`](@ref) for Hermitian matrices `A == A'`, which
```

Code after:
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Symmetric and Hermitian matrices
struct Symmetric{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
    data::S
    uplo::Char

    function Symmetric{T,S}(data, uplo) where {T,S<:AbstractMatrix{<:T}}
        require_one_based_indexing(data)
        (uplo != 'U' && uplo != 'L') && throw_uplo()
        new{T,S}(data, uplo)
    end
end
"""
    Symmetric(A, uplo=:U)

Construct a `Symmetric` view of the upper (if `uplo = :U`) or lower (if `uplo = :L`)
triangle of the matrix `A`.

`Symmetric` views are mainly useful for real-symmetric matrices, for which
specialized algorithms (e.g. for eigenproblems) are enabled for `Symmetric` types.
More generally, see also [`Hermitian(A)`](@ref) for Hermitian matrices `A == A'`, which
is effectively equivalent to `Symmetric` for real matrices but is also useful for
complex matrices.  (Whereas complex `Symmetric` matrices are supported but have few
if any specialized algorithms.)

To compute the symmetric part of a real matrix, or more generally the Hermitian part `(A + A') / 2` of
a real or complex matrix `A`, use [`hermitianpart`](@ref).

# Examples
```jldoctest
julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Matrix{Int64}:
 1  2  3
 4  5  6
 7  8  9

julia> Supper = Symmetric(A)
3×3 Symmetric{Int64, Matrix{Int64}}:
 1  2  3
 2  5  6
 3  6  9

julia> Slower = Symmetric(A, :L)
3×3 Symmetric{Int64, Matrix{Int64}}:
 1  4  7
 4  5  8
Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref).

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) =
    Hermitian(_hermorsympart!(a -> hermitianpart(a, uplo), adjoint, A), uplo)

@inline function _hermorsympart!(real::Function, conj::Function, A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = real(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + conj(A[j, i])) / 2
            A[j, i] = conj(val)
        end
    end
    return A
end


Review comment (refactor):
This function is only used in one place with one set of functions as input so perhaps it's not needed and can just be the body of the `hermitianpart!(::AbstractMatrix)` method.

```suggestion
function hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = hermitianpart(A[j, j], uplo)
        for i in 1:(j - 1)
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return Hermitian(A, uplo)
end
```

But if we're returning a `Hermitian`-wrapped matrix, presumably we don't need to set both `A[i, j]` and `A[j, i]` explicitly?

Code after:
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref) for the corresponding out-of-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::Number) = real(a)

function _hermitianpart!(A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end
Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
[`Symmetric`](@ref) view.

See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)
hermitianpart(a::Number) = _hermitianpart(a)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref).

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::T) where {T<:Number} = convert(Base.promote_op(/, T, Int), real(a))

function _hermitianpart!(A)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end


Review comment (suggestion):
```suggestion
_hermitianpart(a::Number) = real(a)
```
As far as I can tell there is no reason to do a conversion here.

Code after:
"""
    hermitianpart(A, uplo=:U) -> Hermitian

Return the Hermitian part of the square matrix `A`, defined as `(A + A') / 2`, as a
[`Hermitian`](@ref) matrix. For real matrices `A`, this is also known as the symmetric part
of `A`; it is also sometimes called the "operator real part". The optional argument `uplo` controls the corresponding argument of the
[`Hermitian`](@ref) view. For real matrices, the latter is equivalent to a
[`Symmetric`](@ref) view.

See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref) for the corresponding out-of-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::Number) = real(a)

function _hermitianpart!(A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end
Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)
hermitianpart(a::Number) = _hermitianpart(a)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref).

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::T) where {T<:Number} = convert(Base.promote_op(/, T, Int), real(a))

function _hermitianpart!(A)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end


Review comment (refactor):
```suggestion
function _hermitianpart!(A::AbstractMatrix)
```
Might be clearer here to explicitly put this in the signature.

Code after:

Return the Hermitian part of the square matrix `A`, defined as `(A + A') / 2`, as a
[`Hermitian`](@ref) matrix. For real matrices `A`, this is also known as the symmetric part
of `A`; it is also sometimes called the "operator real part". The optional argument `uplo` controls the corresponding argument of the
[`Hermitian`](@ref) view. For real matrices, the latter is equivalent to a
[`Symmetric`](@ref) view.

See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref) for the corresponding out-of-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::Number) = real(a)

function _hermitianpart!(A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end
Repository: JuliaLang/julia
File: base/intfuncs.jl (Julia)

Code before:

# Examples
```jldoctest
julia> ndigits(12345)
5

julia> ndigits(1022, base=16)
3

julia> string(1022, base=16)
"3fe"

julia> ndigits(123, pad=5)
5
```
"""
ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, base))

## integer to string functions ##

function bin(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + max(pad,sizeof(x)<<3-leading_zeros(x))
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = (0x30+(x&0x1)::Unsigned)::Unsigned
        x = (x >> 1)::Unsigned
        i -= 1
    end
    if neg; @inbounds a[1]=0x2d; end
    String(a)
end

function oct(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + max(pad,div((sizeof(x)<<3)-leading_zeros(x)+2,3))
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = 48+(x&0x7)
        x >>= 3
        i -= 1
    end
    if neg; @inbounds a[1]=0x2d; end
    String(a)
end

function dec(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + ndigits(x, base=10, pad=pad)
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = 48+rem(x,10)
        x = oftype(x,div(x,10))
        i -= 1

Review comment (suggestion):
```suggestion
        @inbounds a[i] = 0x30 + ((x % UInt8)::UInt8 & 0x1)
        x >>= 0x1
```
I think this may clarify the intent. As mentioned above, `(pad % Int)::Int` may be safer.

Code after:

# Examples
```jldoctest
julia> ndigits(12345)
5

julia> ndigits(1022, base=16)
3

julia> string(1022, base=16)
"3fe"

julia> ndigits(123, pad=5)
5
```
"""
ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, base))

## integer to string functions ##

function bin(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + max(pad,sizeof(x)<<3-leading_zeros(x))
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = 48+(x&0x1)
        x >>= 1
        i -= 1
    end
    if neg; @inbounds a[1]=0x2d; end
    String(a)
end

function oct(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + max(pad,div((sizeof(x)<<3)-leading_zeros(x)+2,3))
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = 48+(x&0x7)
        x >>= 3
        i -= 1
    end
    if neg; @inbounds a[1]=0x2d; end
    String(a)
end

function dec(x::Unsigned, pad::Integer, neg::Bool)
    i = neg + ndigits(x, base=10, pad=pad)
    a = StringVector(i)
    while i > neg
        @inbounds a[i] = 48+rem(x,10)
        x = oftype(x,div(x,10))
        i -= 1
Repository: JuliaLang/julia
File: base/tuple.jl (Julia)

Code before:
function _setindex(v, i::Integer, args::Vararg{Any,N}) where {N}
    @inline
    return ntuple(j -> ifelse(j == i, v, args[j]), Val{N}())
end


## iterating ##

function iterate(@nospecialize(t::Tuple), i::Int=1)
    @inline
    return (1 <= i <= length(t)) ? (@inbounds t[i], i + 1) : nothing
end

keys(@nospecialize t::Tuple) = OneTo(length(t))

prevind(@nospecialize(t::Tuple), i::Integer) = Int(i)-1
nextind(@nospecialize(t::Tuple), i::Integer) = Int(i)+1

@noinline function throw_eachindex_mismatch_indices(::Tuple{}, inds...)
    throw(DimensionMismatch("all inputs to eachindex must have the same length, got $(join(inds, ", ", " and "))"))
end

function keys(t::Tuple, t2::Tuple...)
    @inline
    lent = length(t)
    all(x->length(x) == lent, t2) || throw_eachindex_mismatch_indices((), t, t2...)
    Base.OneTo(lent)
end

# this allows partial evaluation of bounded sequences of next() calls on tuples,
# while reducing to plain next() for arbitrary iterables.
indexed_iterate(t::Tuple, i::Int, state=1) = (@inline; (getfield(t, i), i+1))
indexed_iterate(a::Array, i::Int, state=1) = (@inline; (a[i], i+1))
function indexed_iterate(I, i)
    x = iterate(I)
    x === nothing && throw(BoundsError(I, i))
    x
end
function indexed_iterate(I, i, state)
    x = iterate(I, state)
    x === nothing && throw(BoundsError(I, i))
    x
end

"""
    Base.rest(collection[, itr_state])

Generic function for taking the tail of `collection`, starting from a specific iteration
state `itr_state`. Return a `Tuple`, if `collection` itself is a `Tuple`, a subtype of
`AbstractVector`, if `collection` is an `AbstractArray`, a subtype of `AbstractString`
if `collection` is an `AbstractString`, and an arbitrary iterator, falling back to

Review comment (suggestion):
```suggestion
    all(==(lent), t2) || throw_eachindex_mismatch_indices((), t, t2...)
```

Code after:
    @boundscheck 1 <= i <= length(x) || throw(BoundsError(x, i))
    @inline
    _setindex(v, i, x...)
end

function _setindex(v, i::Integer, args::Vararg{Any,N}) where {N}
    @inline
    return ntuple(j -> ifelse(j == i, v, args[j]), Val{N}())::NTuple{N, Any}
end


## iterating ##

function iterate(@nospecialize(t::Tuple), i::Int=1)
    @inline
    @_nothrow_meta
    return (1 <= i <= length(t)) ? (t[i], i + 1) : nothing
end

keys(@nospecialize t::Tuple) = OneTo(length(t))

"""
    prevind(A, i)

Return the index before `i` in `A`. The returned index is often equivalent to
`i - 1` for an integer `i`. This function can be useful for generic code.

!!! warning
    The returned index might be out of bounds. Consider using
    [`checkbounds`](@ref).

See also: [`nextind`](@ref).

# Examples
```jldoctest
julia> x = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> prevind(x, 4) # valid result
3

julia> prevind(x, 1) # invalid result
0

julia> prevind(x, CartesianIndex(2, 2)) # valid result
CartesianIndex(1, 2)

julia> prevind(x, CartesianIndex(1, 1)) # invalid result
CartesianIndex(2, 0)
Repository: JuliaLang/julia
File: base/tuple.jl (Julia)

Code before:
function _setindex(v, i::Integer, args::Vararg{Any,N}) where {N}
    @inline
    return ntuple(j -> ifelse(j == i, v, args[j]), Val{N}())
end


## iterating ##

function iterate(@nospecialize(t::Tuple), i::Int=1)
    @inline
    return (1 <= i <= length(t)) ? (@inbounds t[i], i + 1) : nothing
end

keys(@nospecialize t::Tuple) = OneTo(length(t))

prevind(@nospecialize(t::Tuple), i::Integer) = Int(i)-1
nextind(@nospecialize(t::Tuple), i::Integer) = Int(i)+1

@noinline function throw_eachindex_mismatch_indices(::Tuple{}, inds...)
    throw(DimensionMismatch("all inputs to eachindex must have the same length, got $(join(inds, ", ", " and "))"))
end

function keys(t::Tuple, t2::Tuple...)
    @inline
    lent = length(t)
    all(==(lent), t2) || throw_eachindex_mismatch_indices((), t, t2...)
    Base.OneTo(lent)
end

# this allows partial evaluation of bounded sequences of next() calls on tuples,
# while reducing to plain next() for arbitrary iterables.
indexed_iterate(t::Tuple, i::Int, state=1) = (@inline; (getfield(t, i), i+1))
indexed_iterate(a::Array, i::Int, state=1) = (@inline; (a[i], i+1))
function indexed_iterate(I, i)
    x = iterate(I)
    x === nothing && throw(BoundsError(I, i))
    x
end
function indexed_iterate(I, i, state)
    x = iterate(I, state)
    x === nothing && throw(BoundsError(I, i))
    x
end

"""
    Base.rest(collection[, itr_state])

Generic function for taking the tail of `collection`, starting from a specific iteration
state `itr_state`. Return a `Tuple`, if `collection` itself is a `Tuple`, a subtype of
`AbstractVector`, if `collection` is an `AbstractArray`, a subtype of `AbstractString`
if `collection` is an `AbstractString`, and an arbitrary iterator, falling back to

Review comment (suggestion):
```suggestion
    all(t -> length(t)==lent, t2) || throw_eachindex_mismatch_indices((), t, t2...)
```

Code after:
    @boundscheck 1 <= i <= length(x) || throw(BoundsError(x, i))
    @inline
    _setindex(v, i, x...)
end

function _setindex(v, i::Integer, args::Vararg{Any,N}) where {N}
    @inline
    return ntuple(j -> ifelse(j == i, v, args[j]), Val{N}())::NTuple{N, Any}
end


## iterating ##

function iterate(@nospecialize(t::Tuple), i::Int=1)
    @inline
    @_nothrow_meta
    return (1 <= i <= length(t)) ? (t[i], i + 1) : nothing
end

keys(@nospecialize t::Tuple) = OneTo(length(t))

"""
    prevind(A, i)

Return the index before `i` in `A`. The returned index is often equivalent to
`i - 1` for an integer `i`. This function can be useful for generic code.

!!! warning
    The returned index might be out of bounds. Consider using
    [`checkbounds`](@ref).

See also: [`nextind`](@ref).

# Examples
```jldoctest
julia> x = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> prevind(x, 4) # valid result
3

julia> prevind(x, 1) # invalid result
0

julia> prevind(x, CartesianIndex(2, 2)) # valid result
CartesianIndex(1, 2)

julia> prevind(x, CartesianIndex(1, 1)) # invalid result
CartesianIndex(2, 0)