Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports for 1.11.3 #56741

Merged
merged 32 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c3449dc
subtype: fast path for Type == TypeVar (#56640)
N5N3 Nov 26, 2024
f987397
Fix test report alignment (#56789)
IanButterworth Dec 10, 2024
a788519
fix `exp(weirdNaN)` (#56784)
oscardssmith Dec 10, 2024
9a48815
Fix generate_precompile statement grouping & avoid defining new func …
IanButterworth Dec 11, 2024
3fb7f2e
Fix partially_inline for unreachable (#56787)
wsmoses Dec 12, 2024
790081c
bump Pkg to latest 1.11
Dec 16, 2024
5b83838
xref `UnionAll` in the doc string of `where` (#56411)
nsajko Dec 15, 2024
6f6bc95
docs: fix edge case in rational number conversion `float(a//b)` (#56772)
Priynsh Dec 18, 2024
aa276c3
dict docs: document that ordering of keys/values/pairs match iterate …
cossio Dec 18, 2024
06a372f
Extend `Base.rationalize` instead of defining new function (#56793)
sostock Dec 19, 2024
35ffb65
fix precompilation error printing if `CI` is set (#56905)
simeonschaub Dec 25, 2024
3dd91a1
inference: fix inference error from constructing invalid `TypeVar` (#…
aviatesk Oct 21, 2024
d031595
InteractiveUtils.jl: fixes issue where subtypes resolves bindings and…
dgleich Oct 24, 2024
0ff8f82
irinterp: set `IR_FLAG_REFINED` for narrowed `PhiNode`s (#56391)
aviatesk Nov 1, 2024
45d3238
lowering: don't reverse handler order in `(pop-handler-list ...)` (#5…
topolarity Nov 18, 2024
2adfacc
avoid memory leak in mallocarrays linked list
Jan 2, 2025
905e39a
precompileplkgs: release parallel limiter when waiting for another pr…
IanButterworth Dec 17, 2024
1b75f96
fix jl_mutex_lock deadlock under rr (#56644)
vtjnash Nov 22, 2024
bcb1f11
precompilepkgs: respect loaded dependencies when precompiling for loa…
IanButterworth Dec 30, 2024
6e28217
Don't report only-inferred methods as recompiles (#56914)
IanButterworth Jan 2, 2025
9e39755
rearrange jl_delete_thread to be thread-safe (#56097)
vtjnash Oct 11, 2024
bdf8219
precompile: don't waste memory on useless inferred code (#56749)
vtjnash Dec 9, 2024
8c63ce1
fix backport of #56097
KristofferC Jan 7, 2025
cbb7ebc
[BinaryPlatforms] Parse `rc64`/`riscv64` triplets
giordano Jan 8, 2025
ec67820
🤖 [backports-release-1.11] Bump the Pkg stdlib from bac7775db to 2eb8…
DilumAluthgeBot Jan 10, 2025
fa13ea8
Utilize bitshifts correctly in signals-mach.c when storing/reading th…
gbaraldi Mar 28, 2024
115ce5a
REPL: Limit method lookup when completing kwargs (#56963)
IanButterworth Jan 6, 2025
03365f5
fix deepcopy for non-trivial circular references (#56990)
willtebbutt Jan 9, 2025
03ffe4d
broadcast: align `ndims` implementation with intent behind code (#56999)
nsajko Jan 10, 2025
0aa7b95
Miscellaneous `Meta.partially_inline!` fixes (#56813)
topolarity Jan 10, 2025
f66a1cf
fix kwarg limit method backport
KristofferC Jan 14, 2025
343c6ee
Revert "Avoid allocations in views of views (#53231)" (#57044)
KristofferC Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ Return an iterator over all keys in a dictionary.
When the keys are stored internally in a hash table,
as is the case for `Dict`,
the order in which they are returned may vary.
But `keys(a)` and `values(a)` both iterate `a` and
return the elements in the same order.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand All @@ -114,8 +114,8 @@ Return an iterator over all values in a collection.
When the values are stored internally in a hash table,
as is the case for `Dict`,
the order in which they are returned may vary.
But `keys(a)` and `values(a)` both iterate `a` and
return the elements in the same order.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand All @@ -138,6 +138,10 @@ values(a::AbstractDict) = ValueIterator(a)
Return an iterator over `key => value` pairs for any
collection that maps a set of keys to a set of values.
This includes arrays, where the keys are the array indices.
When the entries are stored internally in a hash table,
as is the case for `Dict`, the order in which they are returned may vary.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand Down
1 change: 1 addition & 0 deletions base/binaryplatforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ const arch_mapping = Dict(
"armv7l" => "arm(v7l)?", # if we just see `arm-linux-gnueabihf`, we assume it's `armv7l`
"armv6l" => "armv6l",
"powerpc64le" => "p(ower)?pc64le",
"riscv64" => "(rv64|riscv64)",
)
# Keep this in sync with `CPUID.ISAs_by_family`
# These are the CPUID side of the microarchitectures targeted by GCC flags in BinaryBuilder.jl
Expand Down
9 changes: 7 additions & 2 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,14 @@ Base.@propagate_inbounds function Base.iterate(bc::Broadcasted, s)
end

Base.IteratorSize(::Type{T}) where {T<:Broadcasted} = Base.HasShape{ndims(T)}()
Base.ndims(BC::Type{<:Broadcasted{<:Any,Nothing}}) = _maxndims(fieldtype(BC, :args))
Base.ndims(::Type{<:Broadcasted{<:AbstractArrayStyle{N},Nothing}}) where {N<:Integer} = N
Base.ndims(BC::Type{<:Broadcasted{<:Any,Nothing}}) = _maxndims_broadcasted(BC)
# the `AbstractArrayStyle` type parameter is required to be either equal to `Any` or be an `Int` value
Base.ndims(BC::Type{<:Broadcasted{<:AbstractArrayStyle{Any},Nothing}}) = _maxndims_broadcasted(BC)
Base.ndims(::Type{<:Broadcasted{<:AbstractArrayStyle{N},Nothing}}) where {N} = N::Int

function _maxndims_broadcasted(BC::Type{<:Broadcasted})
_maxndims(fieldtype(BC, :args))
end
_maxndims(::Type{T}) where {T<:Tuple} = reduce(max, ntuple(n -> (F = fieldtype(T, n); F <: Tuple ? 1 : ndims(F)), Base._counttuple(T)))
_maxndims(::Type{<:Tuple{T}}) where {T} = T <: Tuple ? 1 : ndims(T)
function _maxndims(::Type{<:Tuple{T, S}}) where {T, S}
Expand Down
1 change: 1 addition & 0 deletions base/compiler/effects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ is_inaccessiblemem_or_argmemonly(effects::Effects) = effects.inaccessiblememonly

is_consistent_overlay(effects::Effects) = effects.nonoverlayed === CONSISTENT_OVERLAY

# (sync this with codegen.cpp and staticdata.c effects_foldable functions)
function encode_effects(e::Effects)
return ((e.consistent % UInt32) << 0) |
((e.effect_free % UInt32) << 3) |
Expand Down
12 changes: 7 additions & 5 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2075,18 +2075,19 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
unionphi = unionphis[i]
phi = unionphi[1]
t = unionphi[2]
inst = compact.result[phi]
if t === Union{}
stmt = compact[SSAValue(phi)][:stmt]::PhiNode
stmt = inst[:stmt]::PhiNode
kill_phi!(compact, phi_uses, 1:length(stmt.values), SSAValue(phi), stmt, true)
made_changes = true
continue
elseif t === Any
continue
elseif ⊑(𝕃ₒ, compact.result[phi][:type], t)
continue
end
⊏ = strictpartialorder(𝕃ₒ)
t ⊏ inst[:type] || continue
to_drop = Int[]
stmt = compact[SSAValue(phi)][:stmt]
stmt = inst[:stmt]
stmt === nothing && continue
stmt = stmt::PhiNode
for i = 1:length(stmt.values)
Expand All @@ -2098,7 +2099,8 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
push!(to_drop, i)
end
end
compact.result[phi][:type] = t
inst[:type] = t
add_flag!(inst, IR_FLAG_REFINED) # t ⊏ inst[:type]
kill_phi!(compact, phi_uses, to_drop, SSAValue(phi), stmt, false)
made_changes = true
end
Expand Down
12 changes: 10 additions & 2 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -587,8 +587,16 @@ add_tfunc(svec, 0, INT_INF, @nospecs((𝕃::AbstractLattice, args...)->SimpleVec
return TypeVar
end
end
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
lb_valid = lb isa Type || lb isa TypeVar
ub_valid = ub isa Type || ub isa TypeVar
if lb_valid && ub_valid
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
elseif !lb_valid && lb_certain
return Union{}
elseif !ub_valid && ub_certain
return Union{}
end
end
return TypeVar
end
Expand Down
7 changes: 5 additions & 2 deletions base/deepcopy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ function _deepcopy_memory_t(@nospecialize(x::Memory), T, stackdict::IdDict)
end
return dest
end
@eval function deepcopy_internal(x::Array{T, N}, stackdict::IdDict) where {T, N}
function deepcopy_internal(x::Array{T, N}, stackdict::IdDict) where {T, N}
if haskey(stackdict, x)
return stackdict[x]::typeof(x)
end
stackdict[x] = $(Expr(:new, :(Array{T, N}), :(deepcopy_internal(x.ref, stackdict)), :(x.size)))
y = stackdict[x] = Array{T, N}(undef, ntuple(Returns(0), Val{N}()))
setfield!(y, :ref, deepcopy_internal(x.ref, stackdict))
setfield!(y, :size, x.size)
y
end
function deepcopy_internal(x::GenericMemoryRef, stackdict::IdDict)
if haskey(stackdict, x)
Expand Down
2 changes: 1 addition & 1 deletion base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,7 @@ kw"new"
"""
where
The `where` keyword creates a type that is an iterated union of other types, over all
The `where` keyword creates a [`UnionAll`](@ref) type, which may be thought of as an iterated union of other types, over all
values of some variable. For example `Vector{T} where T<:Real` includes all [`Vector`](@ref)s
where the element type is some kind of `Real` number.
Expand Down
4 changes: 2 additions & 2 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ function compilecache_path(pkg::PkgId;
path = nothing
isnothing(sourcepath) && error("Cannot locate source for $(repr("text/plain", pkg))")
for path_to_try in cachepaths
staledeps = stale_cachefile(sourcepath, path_to_try, ignore_loaded = true, requested_flags=flags)
staledeps = stale_cachefile(sourcepath, path_to_try; ignore_loaded, requested_flags=flags)
if staledeps === true
continue
end
Expand Down Expand Up @@ -2555,7 +2555,7 @@ function _require(pkg::PkgId, env=nothing)
parallel_precompile_attempted = true
unlock(require_lock)
try
Precompilation.precompilepkgs([pkg.name]; _from_loading=true)
Precompilation.precompilepkgs([pkg.name]; _from_loading=true, ignore_loaded=false)
finally
lock(require_lock)
end
Expand Down
2 changes: 1 addition & 1 deletion base/mathconstants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ end
Base.@assume_effects :foldable function (::Type{T})(x::_KnownIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}}
Base._irrational_to_float(T, x, r)
end
Base.@assume_effects :foldable function rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
Base.@assume_effects :foldable function Base.rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
Base._rationalize_irrational(T, x, tol)
end
Base.@assume_effects :foldable function Base.lessrational(rx::Rational, x::_KnownIrrational)
Expand Down
21 changes: 21 additions & 0 deletions base/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,29 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
x.edges .+= slot_offset
return x
end
if isa(x, Core.UpsilonNode)
if !isdefined(x, :val)
return x
end
return Core.UpsilonNode(
_partially_inline!(x.val, slot_replacements, type_signature, static_param_values,
slot_offset, statement_offset, boundscheck),
)
end
if isa(x, Core.PhiCNode)
_partially_inline!(x.values, slot_replacements, type_signature, static_param_values,
slot_offset, statement_offset, boundscheck)
end
if isa(x, Core.ReturnNode)
# Unreachable doesn't have val defined
if !isdefined(x, :val)
return x
else
return Core.ReturnNode(
_partially_inline!(x.val, slot_replacements, type_signature, static_param_values,
slot_offset, statement_offset, boundscheck),
)
end
end
if isa(x, Core.GotoIfNot)
return Core.GotoIfNot(
Expand All @@ -376,6 +394,9 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
)
end
if isa(x, Core.EnterNode)
if x.catch_dest == 0
return x
end
return Core.EnterNode(x, x.catch_dest + statement_offset)
end
if isa(x, Expr)
Expand Down
48 changes: 29 additions & 19 deletions base/precompilation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,12 @@ function precompilepkgs(pkgs::Vector{String}=String[];
configs::Union{Config,Vector{Config}}=(``=>Base.CacheFlags()),
io::IO=stderr,
# asking for timing disables fancy mode, as timing is shown in non-fancy mode
fancyprint::Bool = can_fancyprint(io) && !timing)
fancyprint::Bool = can_fancyprint(io) && !timing,
ignore_loaded::Bool=true)
# monomorphize this to avoid latency problems
_precompilepkgs(pkgs, internal_call, strict, warn_loaded, timing, _from_loading,
configs isa Vector{Config} ? configs : [configs],
IOContext{IO}(io), fancyprint)
IOContext{IO}(io), fancyprint, ignore_loaded)
end

function _precompilepkgs(pkgs::Vector{String},
Expand All @@ -419,7 +420,8 @@ function _precompilepkgs(pkgs::Vector{String},
_from_loading::Bool,
configs::Vector{Config},
io::IOContext{IO},
fancyprint::Bool)
fancyprint::Bool,
ignore_loaded::Bool)
requested_pkgs = copy(pkgs) # for understanding user intent

time_start = time_ns()
Expand Down Expand Up @@ -894,7 +896,7 @@ function _precompilepkgs(pkgs::Vector{String},
wait(was_processed[(dep,config)])
end
circular = pkg in circular_deps
is_stale = !Base.isprecompiled(pkg; ignore_loaded=true, stale_cache, cachepath_cache, cachepaths, sourcepath, flags=cacheflags)
is_stale = !Base.isprecompiled(pkg; ignore_loaded, stale_cache, cachepath_cache, cachepaths, sourcepath, flags=cacheflags)
if !circular && is_stale
Base.acquire(parallel_limiter)
is_direct_dep = pkg in direct_deps
Expand All @@ -920,10 +922,10 @@ function _precompilepkgs(pkgs::Vector{String},
try
# allows processes to wait if another process is precompiling a given package to
# a functionally identical package cache (except for preferences, which may differ)
t = @elapsed ret = precompile_pkgs_maybe_cachefile_lock(io, print_lock, fancyprint, pkg_config, pkgspidlocked, hascolor) do
t = @elapsed ret = precompile_pkgs_maybe_cachefile_lock(io, print_lock, fancyprint, pkg_config, pkgspidlocked, hascolor, parallel_limiter, ignore_loaded) do
Base.with_logger(Base.NullLogger()) do
# The false here means we ignore loaded modules, so precompile for a fresh session
keep_loaded_modules = false
# whether to respect already loaded dependency versions
keep_loaded_modules = !ignore_loaded
# for extensions, any extension in our direct dependencies is one we have a right to load
# for packages, we may load any extension (all possible triggers are accounted for above)
loadable_exts = haskey(exts, pkg) ? filter((dep)->haskey(exts, dep), depsmap[pkg]) : nothing
Expand Down Expand Up @@ -1008,9 +1010,11 @@ function _precompilepkgs(pkgs::Vector{String},
plural1 = length(configs) > 1 ? "dependency configurations" : n_loaded == 1 ? "dependency" : "dependencies"
plural2 = n_loaded == 1 ? "a different version is" : "different versions are"
plural3 = n_loaded == 1 ? "" : "s"
plural4 = n_loaded == 1 ? "this package" : "these packages"
print(iostr, "\n ",
color_string(string(n_loaded), Base.warn_color()),
" $(plural1) precompiled but $(plural2) currently loaded. Restart julia to access the new version$(plural3)"
" $(plural1) precompiled but $(plural2) currently loaded. Restart julia to access the new version$(plural3). \
Otherwise, loading dependents of $(plural4) may trigger further precompilation to work with the unexpected version$(plural3)."
)
end
if !isempty(precomperr_deps)
Expand Down Expand Up @@ -1069,7 +1073,7 @@ function _precompilepkgs(pkgs::Vector{String},
direct = strict ? "" : "direct "
err_msg = "The following $n_direct_errs $(direct)dependenc$(pluralde) failed to precompile:\n$(String(take!(err_str)))"
if internal_call # aka. auto-precompilation
if isinteractive() && !get(ENV, "CI", false)
if isinteractive()
plural1 = length(failed_deps) == 1 ? "y" : "ies"
println(io, " ", color_string("$(length(failed_deps))", Base.error_color()), " dependenc$(plural1) errored.")
println(io, " For a report of the errors see `julia> err`. To retry use `pkg> precompile`")
Expand Down Expand Up @@ -1101,7 +1105,7 @@ function _color_string(cstr::String, col::Union{Int64, Symbol}, hascolor)
end

# Can be merged with `maybe_cachefile_lock` in loading?
function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLock, fancyprint::Bool, pkg_config, pkgspidlocked, hascolor)
function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLock, fancyprint::Bool, pkg_config, pkgspidlocked, hascolor, parallel_limiter::Base.Semaphore, ignore_loaded::Bool)
pkg, config = pkg_config
flags, cacheflags = config
FileWatching = Base.loaded_modules[Base.PkgId(Base.UUID("7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"), "FileWatching")]
Expand All @@ -1122,15 +1126,21 @@ function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLo
!fancyprint && lock(print_lock) do
println(io, " ", pkg.name, _color_string(" Being precompiled by $(pkgspidlocked[pkg_config])", Base.info_color(), hascolor))
end
# wait until the lock is available
FileWatching.mkpidlock(pidfile; stale_age) do
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded=true, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
return f() # precompile
end
Base.release(parallel_limiter) # release so other work can be done while waiting
try
# wait until the lock is available
@invokelatest Base.mkpidlock_hook(() -> begin
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
Base.acquire(f, parallel_limiter) # precompile
end
end,
pidfile; stale_age)
finally
Base.acquire(parallel_limiter) # re-acquire so the outer release is balanced
end
end
return cachefile
Expand Down
2 changes: 2 additions & 0 deletions base/special/exp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ end
small_part = muladd(jU, expm1b_kernel(base, r), jL) + jU

if !(abs(x) <= SUBNORM_EXP(base, T))
isnan(x) && return x
x >= MAX_EXP(base, T) && return Inf
x <= MIN_EXP(base, T) && return 0.0
if k <= -53
Expand Down Expand Up @@ -243,6 +244,7 @@ end
hi, lo = Base.canonicalize2(1.0, kern)
small_part = fma(jU, hi, muladd(jU, (lo+xlo), very_small))
if !(abs(x) <= SUBNORM_EXP(base, T))
isnan(x) && return x
x >= MAX_EXP(base, T) && return Inf
x <= MIN_EXP(base, T) && return 0.0
if k <= -53
Expand Down
6 changes: 3 additions & 3 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -295,18 +295,18 @@ reindex(idxs::Tuple{Slice, Vararg{Any}}, subidxs::Tuple{Any, Vararg{Any}}) =

# Re-index into parent vectors with one subindex
reindex(idxs::Tuple{AbstractVector, Vararg{Any}}, subidxs::Tuple{Any, Vararg{Any}}) =
(@_propagate_inbounds_meta; (maybeview(idxs[1], subidxs[1]), reindex(tail(idxs), tail(subidxs))...))
(@_propagate_inbounds_meta; (idxs[1][subidxs[1]], reindex(tail(idxs), tail(subidxs))...))

# Parent matrices are re-indexed with two sub-indices
reindex(idxs::Tuple{AbstractMatrix, Vararg{Any}}, subidxs::Tuple{Any, Any, Vararg{Any}}) =
(@_propagate_inbounds_meta; (maybeview(idxs[1], subidxs[1], subidxs[2]), reindex(tail(idxs), tail(tail(subidxs)))...))
(@_propagate_inbounds_meta; (idxs[1][subidxs[1], subidxs[2]], reindex(tail(idxs), tail(tail(subidxs)))...))

# In general, we index N-dimensional parent arrays with N indices
@generated function reindex(idxs::Tuple{AbstractArray{T,N}, Vararg{Any}}, subidxs::Tuple{Vararg{Any}}) where {T,N}
if length(subidxs.parameters) >= N
subs = [:(subidxs[$d]) for d in 1:N]
tail = [:(subidxs[$d]) for d in N+1:length(subidxs.parameters)]
:(@_propagate_inbounds_meta; (maybeview(idxs[1], $(subs...)), reindex(tail(idxs), ($(tail...),))...))
:(@_propagate_inbounds_meta; (idxs[1][$(subs...)], reindex(tail(idxs), ($(tail...),))...))
else
:(throw(ArgumentError("cannot re-index SubArray with fewer indices than dimensions\nThis should not occur; please submit a bug report.")))
end
Expand Down
Loading
Loading