Why does indexing into CartesianIndices lead to excessive runtime dispatch?

This just looks so weird to me. The code is really simply:

function neighbors(d::Int)
    n_ = CartesianIndices((fill(-1:1, d)...,))
    n  = n_[begin:end//2] #This line runtime errors
end

using JET

@report_opt neighbors(2)


═════ 106 possible errors found ═════
┌ neighbors(d::Int64) @ Main c:\git\SPHExample\example\TempRepoCLL.jl:39
│┌ firstindex(a::CartesianIndices{N, R} where {N, R<:Tuple{Vararg{UnitRange{Int64}, N}}}) @ Base ./abstractarray.jl:446
││┌ eachindex(::IndexLinear, A::CartesianIndices{N, R} where {N, R<:Tuple{Vararg{UnitRange{Int64}, N}}}) @ Base ./abstractarray.jl:385
│││┌ oneto(r::Any) @ Base ./range.jl:469
││││┌ Base.OneTo(r::AbstractRange{T}) where T<:Integer @ Base ./range.jl:468
│││││┌ Base.OneTo{T}(r::Base.OneTo) where T<:Integer @ Base ./range.jl:1301
││││││┌ (::Type{Base.OneTo{T}} where T<:Integer)(stop::Integer) @ Base ./range.jl:453
│││││││┌ (::Base.var"#throwbool#81")(r::Integer) @ Base ./range.jl:452
││││││││┌ string(::String, ::Integer, ::String) @ Base ./strings/io.jl:189
│││││││││┌ print_to_string(::String, ::Integer, ::String) @ Base ./strings/io.jl:148
││││││││││┌ print(io::IOBuffer, n::Unsigned) @ Base ./show.jl:1197
│││││││││││┌ string(n::Unsigned) @ Base ./intfuncs.jl:833
││││││││││││┌ string(n::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:837
│││││││││││││┌ bin(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:715
││││││││││││││┌ setindex!(::Vector{UInt8}, ::UInt8, ::Union{Integer, CartesianIndex}) @ Base ./multidimensional.jl:698
│││││││││││││││┌ to_indices(A::Vector{UInt8}, I::Tuple{Integer}) @ Base ./indices.jl:350
││││││││││││││││┌ to_indices(A::Vector{UInt8}, inds::Tuple{}, I::Tuple{Integer}) @ Base ./indices.jl:354
│││││││││││││││││┌ _to_indices1(A::Vector{UInt8}, inds::Tuple{}, I1::Integer) @ Base ./indices.jl:359
││││││││││││││││││┌ to_index(A::Vector{UInt8}, i::Integer) @ Base ./indices.jl:277
│││││││││││││││││││┌ to_index(i::Bool) @ Base ./indices.jl:293
││││││││││││││││││││┌ string(::String, ::Bool, ::String) @ Base ./strings/io.jl:189
│││││││││││││││││││││┌ print_to_string(::String, ::Vararg{Any}) @ Base ./strings/io.jl:143
││││││││││││││││││││││ runtime dispatch detected: Base._str_sizehint(%15::Any)::Int64
│││││││││││││││││││││└────────────────────
│││││││││││││││││││││┌ print_to_string(::String, ::Vararg{Any}) @ Base ./strings/io.jl:148
││││││││││││││││││││││ runtime dispatch detected: print(%40::IOBuffer, %53::Any)::Any
│││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ string(::String, ::Bool, ::String) @ Base ./strings/io.jl:189
│││││││││││││││││││││ failed to optimize due to recursion: string(::String, ::Bool, ::String)
││││││││││││││││││││└────────────────────
│││││││││││││││││││┌ to_index(i::Bool) @ Base ./indices.jl:293
││││││││││││││││││││ failed to optimize due to recursion: Base.to_index(::Bool)
│││││││││││││││││││└────────────────────
││││││││││││││││┌ to_indices(A::Vector{UInt8}, inds::Tuple{}, I::Tuple{Integer}) @ Base ./indices.jl:354
│││││││││││││││││ runtime dispatch detected: Base._to_indices1(A::Vector{UInt8}, inds::Tuple{}, %1::Integer)::Tuple{Int64}
││││││││││││││││└────────────────────
│││││││││││││││┌ to_indices(A::Vector{UInt8}, I::Tuple{Union{Integer, CartesianIndex}}) @ Base ./multidimensional.jl:859
││││││││││││││││┌ to_indices(A::Vector{UInt8}, inds::Tuple{}, I::Tuple{Union{Integer, CartesianIndex}}) @ Base ./indices.jl:355
│││││││││││││││││┌ _cutdim(inds::Tuple{}, I1::CartesianIndex) @ Base ./multidimensional.jl:863
││││││││││││││││││┌ split(t::Tuple{}, V::Val) @ Base.IteratorsMD ./multidimensional.jl:487
│││││││││││││││││││ runtime dispatch detected: Base.IteratorsMD.ntuple(Returns{Bool}(true), V::Val)::Any
││││││││││││││││││└────────────────────
││││││││││││││││┌ to_indices(A::Vector{UInt8}, inds::Tuple{}, I::Tuple{Union{Integer, CartesianIndex}}) @ Base ./indices.jl:354
│││││││││││││││││ runtime dispatch detected: Base._to_indices1(A::Vector{UInt8}, inds::Tuple{}, %1::Union{Integer, CartesianIndex})::Any
││││││││││││││││└────────────────────
││││││││││││││││┌ to_indices(A::Vector{UInt8}, inds::Tuple{}, I::Tuple{Union{Integer, CartesianIndex}}) @ Base ./indices.jl:355
│││││││││││││││││ runtime dispatch detected: Base._cutdim(inds::Tuple{}, %3::Union{Integer, CartesianIndex})::Tuple{}
││││││││││││││││└────────────────────
││││││││││││││┌ setindex!(A::Vector{UInt8}, v::UInt8, I::Any) @ Base ./abstractarray.jl:1393
│││││││││││││││ runtime dispatch detected: to_indices(A::Vector{UInt8}, I::Tuple{Any})::Any
││││││││││││││└────────────────────
│││││││││││││┌ bin(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:719
││││││││││││││┌ >>(x::Unsigned, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Unsigned >> 4)::Any
││││││││││││││└────────────────────
│││││││││││││┌ bin(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:724
││││││││││││││┌ >>(x::Integer, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Integer >> 1)::Any
││││││││││││││└────────────────────
││││││││││││┌ string(n::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:840
│││││││││││││┌ oct(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:738
││││││││││││││┌ >>(x::Unsigned, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Unsigned >> 3)::Any
││││││││││││││└────────────────────
││││││││││││││┌ >>(x::Integer, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Integer >> 3)::Any
││││││││││││││└────────────────────
││││││││││││┌ string(n::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:843
│││││││││││││┌ dec(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:749
││││││││││││││┌ kwcall(::@NamedTuple{pad::Int64}, ::typeof(ndigits), x::Unsigned) @ Base ./intfuncs.jl:700
│││││││││││││││┌ ndigits(x::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:700
││││││││││││││││┌ ndigits0z(x::Unsigned, b::Int64) @ Base ./intfuncs.jl:659
│││││││││││││││││┌ ndigits0znb(x::Unsigned, b::Int64) @ Base ./intfuncs.jl:578
││││││││││││││││││┌ !=(x::Unsigned, y::Int64) @ Base ./operators.jl:276
│││││││││││││││││││┌ ==(x::Unsigned, y::Int64) @ Base ./promotion.jl:461
││││││││││││││││││││┌ promote(x::Unsigned, y::Int64) @ Base ./promotion.jl:393
│││││││││││││││││││││┌ _promote(x::Unsigned, y::Int64) @ Base ./promotion.jl:369
││││││││││││││││││││││┌ promote_type(::Type{T} where T<:Unsigned, ::Type{Int64}) @ Base ./promotion.jl:313
│││││││││││││││││││││││┌ promote_result(::Type{T} where T<:Unsigned, ::Type{Int64}, ::Type{T}, ::Type{Int64}) where T @ Base ./promotion.jl:333
││││││││││││││││││││││││┌ promote_type(::Type, ::Type{Int64}) @ Base ./promotion.jl:313
│││││││││││││││││││││││││┌ promote_result(::Type{T}, ::Type{Int64}, ::Type{Union{}}, ::Type{Union{}}) where T @ Base ./promotion.jl:336
││││││││││││││││││││││││││┌ typejoin(a::Type, b::Type{Int64}) @ Base ./promotion.jl:34
│││││││││││││││││││││││││││┌ typejoin(a::Any, b::Type{Int64}) @ Base ./promotion.jl:38
││││││││││││││││││││││││││││┌ typejoin(a::Any, b::Any) @ Base ./promotion.jl:127
│││││││││││││││││││││││││││││ runtime dispatch detected: Base.UnionAll(%403::Any, %405::Any)::Any
││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││┌ typejoin(a::Any, b::Type{Int64}) @ Base ./promotion.jl:127
││││││││││││││││││││││││││││ runtime dispatch detected: Base.UnionAll(%381::Any, %383::Any)::Any
│││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││┌ typejoin(a::Type, b::Type{Int64}) @ Base ./promotion.jl:127
│││││││││││││││││││││││││││ runtime dispatch detected: Base.UnionAll(%376::Any, %378::Any)::Any
││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││┌ promote_result(::Type, ::Type{Int64}, ::Type{T}, ::Type{Int64}) where T @ Base ./promotion.jl:333
│││││││││││││││││││││││││ runtime dispatch detected: promote_type(%1::Type, ::Int64)::Any
││││││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ promote(x::Unsigned, y::Int64) @ Base ./promotion.jl:394
│││││││││││││││││││││┌ not_sametype(x::T, y::T) where T<:Tuple{Unsigned, Int64} @ Base ./promotion.jl:411
││││││││││││││││││││││┌ sametype_error(input::Tuple{Unsigned, Int64}) @ Base ./promotion.jl:417
│││││││││││││││││││││││┌ map(f::Base.var"#46#47", t::Tuple{Unsigned, Int64}) @ Base ./tuple.jl:292
││││││││││││││││││││││││┌ (::Base.var"#46#47")(x::Unsigned) @ Base ./promotion.jl:418
│││││││││││││││││││││││││┌ string(xs::Type{<:Unsigned}) @ Base ./strings/io.jl:189
││││││││││││││││││││││││││┌ print_to_string(xs::Type) @ Base ./strings/io.jl:148
│││││││││││││││││││││││││││┌ print(io::IOBuffer, x::Type) @ Base ./strings/io.jl:35
││││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type) @ Base ./show.jl:953
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:958
││││││││││││││││││││││││││││││┌ show_typealias(io::IOBuffer, x::Type) @ Base ./show.jl:793
│││││││││││││││││││││││││││││││┌ make_typealias(x::Type) @ Base ./show.jl:603
││││││││││││││││││││││││││││││││┌ modulesof!(s::Set{Module}, x::Type) @ Base ./show.jl:578
│││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.modulesof!(s::Set{Module}, %20::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ modulesof!(s::Set{Module}, x::Type) @ Base ./show.jl:579
│││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.modulesof!(s::Set{Module}, %35::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ modulesof!(s::Set{Module}, x::TypeVar) @ Base ./show.jl:572
│││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.modulesof!(s::Set{Module}, %1::Any)::Set{Module}
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_typealias(io::IOBuffer, x::Type) @ Base ./show.jl:796
│││││││││││││││││││││││││││││││┌ show_typealias(io::IOBuffer, name::GlobalRef, x::Type, env::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:743
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOContext{IOBuffer}, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:707
│││││││││││││││││││││││││││││││││┌ show(io::IOContext{IOBuffer}, tv::TypeVar) @ Base ./show.jl:2737
││││││││││││││││││││││││││││││││││┌ (::Base.var"#show_bound#566")(io::IOContext{IOBuffer}, b::Any) @ Base ./show.jl:2729
│││││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, b::Any)::Any
││││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOContext{IOBuffer}, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:702
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %243::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOContext{IOBuffer}, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:705
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %294::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOContext{IOBuffer}, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:710
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %192::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:961
││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType) @ Base ./show.jl:1077
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1080
││││││││││││││││││││││││││││││││┌ maybe_kws_nt(x::DataType) @ Base ./show.jl:1068
│││││││││││││││││││││││││││││││││ runtime dispatch detected: eltype(%79::DataType)::Any
││││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1130
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOBuffer, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:707
│││││││││││││││││││││││││││││││││┌ show(io::IOBuffer, tv::TypeVar) @ Base ./show.jl:2737
││││││││││││││││││││││││││││││││││┌ (::Base.var"#show_bound#566")(io::IOBuffer, b::Any) @ Base ./show.jl:2729
│││││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, b::Any)::Any
││││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOBuffer, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:702
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %241::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOBuffer, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:705
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %291::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ show_typeparams(io::IOBuffer, env::Core.SimpleVector, orig::Core.SimpleVector, wheres::Vector{TypeVar}) @ Base ./show.jl:710
│││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %191::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1096
││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %94::Any)::Any
│││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1102
││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %141::Any)::Any
│││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1106
││││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %162::Any)::Any
│││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││││┌ show_datatype(io::IOBuffer, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1116
││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.show_at_namedtuple(io::IOBuffer, %219::Tuple, %220::DataType)::Any
│││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:964
││││││││││││││││││││││││││││││┌ show_unionaliases(io::IOBuffer, x::Union) @ Base ./show.jl:884
│││││││││││││││││││││││││││││││┌ make_typealiases(x::Union) @ Base ./show.jl:805
││││││││││││││││││││││││││││││││┌ modulesof!(s::Set{Module}, x::Union) @ Base ./show.jl:578
│││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.modulesof!(s::Set{Module}, %3::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││││┌ modulesof!(s::Set{Module}, x::Union) @ Base ./show.jl:579
│││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.modulesof!(s::Set{Module}, %17::Any)::Any
││││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_unionaliases(io::IOBuffer, x::Union) @ Base ./show.jl:897
│││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOBuffer, %50::Any)::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_unionaliases(io::IOBuffer, x::Union) @ Base ./show.jl:903
│││││││││││││││││││││││││││││││ runtime dispatch detected: Base.show_typealias(io::IOBuffer, %133::Any, x::Union, %131::Core.SimpleVector, %132::Vector{TypeVar})::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_unionaliases(io::IOBuffer, x::Union) @ Base ./show.jl:911
│││││││││││││││││││││││││││││││ runtime dispatch detected: Base.show_typealias(io::IOBuffer, %179::Any, x::Union, %177::Core.SimpleVector, %178::Vector{TypeVar})::Any
││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:968
││││││││││││││││││││││││││││││┌ show_delim_array(io::IOBuffer, itr::Vector{Any}, op::Char, delim::Char, cl::Char, delim_one::Bool) @ Base ./show.jl:1335
│││││││││││││││││││││││││││││││┌ show_delim_array(io::IOBuffer, itr::Vector{Any}, op::Char, delim::Char, cl::Char, delim_one::Bool, i1::Int64, l::Int64) @ Base ./show.jl:1346
││││││││││││││││││││││││││││││││ runtime dispatch detected: show(%4::IOContext{IOBuffer}, %41::Any)::Any
│││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:995
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1129
│││││││││││││││││││││││││││││││┌ show_type_name(io::IOContext{IOBuffer}, tn::Core.TypeName) @ Base ./show.jl:1042
││││││││││││││││││││││││││││││││ runtime dispatch detected: Base.isvisible(%32::Symbol, %89::Module, %83::Any)::Bool
│││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1096
│││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %94::Any)::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1102
│││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %144::Any)::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1106
│││││││││││││││││││││││││││││││ runtime dispatch detected: show(io::IOContext{IOBuffer}, %166::Any)::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1116
│││││││││││││││││││││││││││││││ runtime dispatch detected: Base.show_at_namedtuple(io::IOContext{IOBuffer}, %225::Tuple, %226::DataType)::Any
││││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││││┌ show_datatype(io::IOContext{IOBuffer}, x::DataType, wheres::Vector{TypeVar}) @ Base ./show.jl:1124
│││││││││││││││││││││││││││││││ runtime dispatch detected: Base.show_at_namedtuple(io::IOContext{IOBuffer}, %268::Tuple, %273::DataType)::Any
││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││││││┌ _show_type(io::IOBuffer, x::Type) @ Base ./show.jl:997
││││││││││││││││││││││││││││││ runtime dispatch detected: show(%74::IOContext{IOBuffer}, %75::Any)::Any
│││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type) @ Base ./show.jl:953
│││││││││││││││││││││││││││││ runtime dispatch detected: Base._show_type(io::IOBuffer, x::Type)::Nothing
││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││┌ (::Base.var"#46#47")(x::Int64) @ Base ./promotion.jl:418
│││││││││││││││││││││││││┌ string(xs::Type{Int64}) @ Base ./strings/io.jl:189
││││││││││││││││││││││││││┌ print_to_string(xs::Type{Int64}) @ Base ./strings/io.jl:148
│││││││││││││││││││││││││││┌ print(io::IOBuffer, x::Type{Int64}) @ Base ./strings/io.jl:35
││││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type{Int64}) @ Base ./show.jl:953
│││││││││││││││││││││││││││││ runtime dispatch detected: Base._show_type(io::IOBuffer, x::Type{Int64})::Nothing
││││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ promote(x::Unsigned, y::Int64) @ Base ./promotion.jl:393
│││││││││││││││││││││ runtime dispatch detected: Base._promote(x::Unsigned, y::Int64)::Tuple{Any, Any}
││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ promote(x::Unsigned, y::Int64) @ Base ./promotion.jl:394
│││││││││││││││││││││ runtime dispatch detected: Base.not_sametype(%4::Tuple{Unsigned, Int64}, %5::Tuple{Any, Any})::Any
││││││││││││││││││││└────────────────────
│││││││││││││││││┌ ndigits0znb(x::Unsigned, b::Int64) @ Base ./intfuncs.jl:579
││││││││││││││││││┌ fld(x::Unsigned, y::Int64) @ Base ./div.jl:332
│││││││││││││││││││┌ div(x::Unsigned, y::Int64, ::RoundingMode{:Down}) @ Base ./div.jl:283
││││││││││││││││││││┌ divrem(x::Unsigned, y::Int64) @ Base ./int.jl:241
│││││││││││││││││││││┌ divrem(x::Unsigned, y::UInt64) @ Base ./div.jl:179
││││││││││││││││││││││┌ divrem(a::Unsigned, b::UInt64, r::RoundingMode{:ToZero}) @ Base ./div.jl:201
│││││││││││││││││││││││┌ div(a::Unsigned, b::UInt64) @ Base ./div.jl:47
││││││││││││││││││││││││┌ div(x::Unsigned, y::UInt64, r::RoundingMode{:ToZero}) @ Base ./div.jl:343
│││││││││││││││││││││││││┌ promote(x::Unsigned, y::UInt64) @ Base ./promotion.jl:393
││││││││││││││││││││││││││┌ _promote(x::Unsigned, y::UInt64) @ Base ./promotion.jl:370
│││││││││││││││││││││││││││ runtime dispatch detected: convert(%77::Any, x::Unsigned)::Any
││││││││││││││││││││││││││└────────────────────
││││││││││││││││││││││││││┌ _promote(x::Unsigned, y::UInt64) @ Base ./promotion.jl:370
│││││││││││││││││││││││││││ runtime dispatch detected: convert(%77::Any, y::UInt64)::Any
││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││││││││┌ promote(x::Unsigned, y::UInt64) @ Base ./promotion.jl:394
││││││││││││││││││││││││││┌ not_sametype(x::T, y::T) where T<:Tuple{Unsigned, UInt64} @ Base ./promotion.jl:411
│││││││││││││││││││││││││││┌ sametype_error(input::Tuple{Unsigned, UInt64}) @ Base ./promotion.jl:417
││││││││││││││││││││││││││││┌ map(f::Base.var"#46#47", t::Tuple{Unsigned, UInt64}) @ Base ./tuple.jl:292
│││││││││││││││││││││││││││││┌ (::Base.var"#46#47")(x::UInt64) @ Base ./promotion.jl:418
││││││││││││││││││││││││││││││┌ string(xs::Type{UInt64}) @ Base ./strings/io.jl:189
│││││││││││││││││││││││││││││││┌ print_to_string(xs::Type{UInt64}) @ Base ./strings/io.jl:148
││││││││││││││││││││││││││││││││┌ print(io::IOBuffer, x::Type{UInt64}) @ Base ./strings/io.jl:35
│││││││││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type{UInt64}) @ Base ./show.jl:953
││││││││││││││││││││││││││││││││││ runtime dispatch detected: Base._show_type(io::IOBuffer, x::Type{UInt64})::Nothing
│││││││││││││││││││││││││││││││││└────────────────────
│││││││││││││││││││┌ div(x::Unsigned, y::Int64, ::RoundingMode{:Down}) @ Base ./div.jl:284
││││││││││││││││││││┌ &(a::Bool, b::Integer) @ Base ./int.jl:1065
│││││││││││││││││││││┌ promote_typeof(x::Bool, xs::Integer) @ Base ./promotion.jl:373
││││││││││││││││││││││┌ promote_type(::Type{Bool}, ::Type{<:Integer}) @ Base ./promotion.jl:313
│││││││││││││││││││││││┌ promote_result(::Type{Bool}, ::Type{<:Integer}, ::Type{T}, ::Type{S}) where {T<:Integer, S} @ Base ./promotion.jl:333
││││││││││││││││││││││││ runtime dispatch detected: promote_type(%1::Type{T} where T<:Integer, %2::Type)::Any
│││││││││││││││││││││││└────────────────────
│││││││││││││││││││││┌ promote_typeof(x::Bool, xs::Integer) @ Base ./promotion.jl:373
││││││││││││││││││││││ runtime dispatch detected: promote_type(::Bool, %2::Type{<:Integer})::Any
│││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ &(a::Bool, b::Integer) @ Base ./int.jl:1067
│││││││││││││││││││││┌ not_sametype(x::T, y::T) where T<:Tuple{Bool, Integer} @ Base ./promotion.jl:411
││││││││││││││││││││││┌ sametype_error(input::Tuple{Bool, Integer}) @ Base ./promotion.jl:417
│││││││││││││││││││││││┌ map(f::Base.var"#46#47", t::Tuple{Bool, Integer}) @ Base ./tuple.jl:292
││││││││││││││││││││││││┌ (::Base.var"#46#47")(x::Bool) @ Base ./promotion.jl:418
│││││││││││││││││││││││││┌ string(xs::Type{Bool}) @ Base ./strings/io.jl:189
││││││││││││││││││││││││││┌ print_to_string(xs::Type{Bool}) @ Base ./strings/io.jl:148
│││││││││││││││││││││││││││┌ print(io::IOBuffer, x::Type{Bool}) @ Base ./strings/io.jl:35
││││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type{Bool}) @ Base ./show.jl:953
│││││││││││││││││││││││││││││ runtime dispatch detected: Base._show_type(io::IOBuffer, x::Type{Bool})::Nothing
││││││││││││││││││││││││││││└────────────────────
││││││││││││││││┌ ndigits0z(x::Unsigned, b::Int64) @ Base ./intfuncs.jl:661
│││││││││││││││││┌ ndigits0zpb(x::Unsigned, b::Int64) @ Base ./intfuncs.jl:611
││││││││││││││││││┌ >(x::Unsigned, y::Int64) @ Base ./operators.jl:378
│││││││││││││││││││┌ <(x::Int64, y::Unsigned) @ Base ./promotion.jl:462
││││││││││││││││││││┌ promote(x::Int64, y::Unsigned) @ Base ./promotion.jl:393
│││││││││││││││││││││┌ _promote(x::Int64, y::Unsigned) @ Base ./promotion.jl:369
││││││││││││││││││││││┌ promote_type(::Type{Int64}, ::Type{S} where S<:Unsigned) @ Base ./promotion.jl:313
│││││││││││││││││││││││┌ promote_result(::Type{Int64}, ::Type{S} where S<:Unsigned, ::Type{Int64}, ::Type{S}) where S @ Base ./promotion.jl:333
││││││││││││││││││││││││┌ promote_result(::Type{Int64}, ::Type, ::Type{Int64}, ::Type{S}) where S @ Base ./promotion.jl:333
│││││││││││││││││││││││││ runtime dispatch detected: promote_type(::Int64, %1::Type)::Any
││││││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ promote(x::Int64, y::Unsigned) @ Base ./promotion.jl:393
│││││││││││││││││││││ runtime dispatch detected: Base._promote(x::Int64, y::Unsigned)::Tuple{Any, Any}
││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ promote(x::Int64, y::Unsigned) @ Base ./promotion.jl:394
│││││││││││││││││││││ runtime dispatch detected: Base.not_sametype(%4::Tuple{Int64, Unsigned}, %5::Tuple{Any, Any})::Any
││││││││││││││││││││└────────────────────
│││││││││││││┌ dec(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:753
││││││││││││││┌ divrem(x::Unsigned, y::UInt8) @ Base ./div.jl:179
│││││││││││││││┌ divrem(a::Unsigned, b::UInt8, r::RoundingMode{:ToZero}) @ Base ./div.jl:201
││││││││││││││││┌ div(a::Unsigned, b::UInt8) @ Base ./div.jl:47
│││││││││││││││││┌ div(x::Unsigned, y::UInt8, r::RoundingMode{:ToZero}) @ Base ./div.jl:343
││││││││││││││││││┌ promote(x::Unsigned, y::UInt8) @ Base ./promotion.jl:393
│││││││││││││││││││┌ _promote(x::Unsigned, y::UInt8) @ Base ./promotion.jl:369
││││││││││││││││││││┌ promote_type(::Type{T} where T<:Unsigned, ::Type{UInt8}) @ Base ./promotion.jl:313
│││││││││││││││││││││┌ promote_result(::Type{T} where T<:Unsigned, ::Type{UInt8}, ::Type{T}, ::Type{UInt8}) where T @ Base ./promotion.jl:333
││││││││││││││││││││││┌ promote_result(::Type, ::Type{UInt8}, ::Type{T}, ::Type{UInt8}) where T @ Base ./promotion.jl:333
│││││││││││││││││││││││ runtime dispatch detected: promote_type(%1::Type, ::UInt8)::Any
││││││││││││││││││││││└────────────────────
││││││││││││││││││┌ promote(x::Unsigned, y::UInt8) @ Base ./promotion.jl:394
│││││││││││││││││││┌ not_sametype(x::T, y::T) where T<:Tuple{Unsigned, UInt8} @ Base ./promotion.jl:411
││││││││││││││││││││┌ sametype_error(input::Tuple{Unsigned, UInt8}) @ Base ./promotion.jl:417
│││││││││││││││││││││┌ map(f::Base.var"#46#47", t::Tuple{Unsigned, UInt8}) @ Base ./tuple.jl:292
││││││││││││││││││││││┌ (::Base.var"#46#47")(x::UInt8) @ Base ./promotion.jl:418
│││││││││││││││││││││││┌ string(xs::Type{UInt8}) @ Base ./strings/io.jl:189
││││││││││││││││││││││││┌ print_to_string(xs::Type{UInt8}) @ Base ./strings/io.jl:148
│││││││││││││││││││││││││┌ print(io::IOBuffer, x::Type{UInt8}) @ Base ./strings/io.jl:35
││││││││││││││││││││││││││┌ show(io::IOBuffer, x::Type{UInt8}) @ Base ./show.jl:953
│││││││││││││││││││││││││││ runtime dispatch detected: Base._show_type(io::IOBuffer, x::Type{UInt8})::Nothing
││││││││││││││││││││││││││└────────────────────
││││││││││││││││││┌ promote(x::Unsigned, y::UInt8) @ Base ./promotion.jl:393
│││││││││││││││││││ runtime dispatch detected: Base._promote(x::Unsigned, y::UInt8)::Tuple{Any, Any}
││││││││││││││││││└────────────────────
││││││││││││││││││┌ promote(x::Unsigned, y::UInt8) @ Base ./promotion.jl:394
│││││││││││││││││││ runtime dispatch detected: Base.not_sametype(%4::Tuple{Unsigned, UInt8}, %5::Tuple{Any, Any})::Any
││││││││││││││││││└────────────────────
││││││││││││┌ string(n::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:846
│││││││││││││┌ hex(x::Unsigned, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:777
││││││││││││││┌ >>(x::Unsigned, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Unsigned >> 8)::Any
││││││││││││││└────────────────────
││││││││││││││┌ >>(x::Integer, c::UInt8) @ Base ./operators.jl:701
│││││││││││││││ runtime dispatch detected: (x::Integer >> 8)::Any
││││││││││││││└────────────────────
││││││││││││┌ string(n::Unsigned; base::Int64, pad::Int64) @ Base ./intfuncs.jl:848
│││││││││││││┌ _base(base::Int64, x::Integer, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:792
││││││││││││││┌ |(a::Integer, b::Bool) @ Base ./int.jl:1065
│││││││││││││││┌ promote_typeof(x::Integer, xs::Bool) @ Base ./promotion.jl:373
││││││││││││││││┌ promote_type(::Type{<:Integer}, ::Type{Bool}) @ Base ./promotion.jl:313
│││││││││││││││││┌ promote_result(::Type{<:Integer}, ::Type{Bool}, ::Type{T}, ::Type{S}) where {T, S<:Integer} @ Base ./promotion.jl:333
││││││││││││││││││ runtime dispatch detected: promote_type(%1::Type, %2::Type{S} where S<:Integer)::Any
│││││││││││││││││└────────────────────
│││││││││││││││┌ promote_typeof(x::Integer, xs::Bool) @ Base ./promotion.jl:373
││││││││││││││││ runtime dispatch detected: promote_type(%1::Type{<:Integer}, ::Bool)::Any
│││││││││││││││└────────────────────
│││││││││││││┌ _base(base::Int64, x::Integer, pad::Int64, neg::Bool) @ Base ./intfuncs.jl:796
││││││││││││││┌ kwcall(::@NamedTuple{base::Int64, pad::Int64}, ::typeof(ndigits), x::Integer) @ Base ./intfuncs.jl:700
│││││││││││││││┌ ndigits(x::Integer; base::Int64, pad::Int64) @ Base ./intfuncs.jl:700
││││││││││││││││┌ ndigits0z(x::Integer, b::Int64) @ Base ./intfuncs.jl:661
│││││││││││││││││┌ ndigits0zpb(x::BigInt, b::Int64) @ Base.GMP ./gmp.jl:813
││││││││││││││││││┌ ^(x::BigInt, y::Int64) @ Base.GMP ./gmp.jl:654
│││││││││││││││││││┌ bigint_pow(x::BigInt, y::Int64) @ Base.GMP ./gmp.jl:647
││││││││││││││││││││┌ (::Base.GMP.var"#throw1#3")(y::Int64) @ Base.GMP ./gmp.jl:632
│││││││││││││││││││││┌ string(::String, ::Int64, ::String) @ Base ./strings/io.jl:189
││││││││││││││││││││││ failed to optimize due to recursion: string(::String, ::Int64, ::String)
│││││││││││││││││││││└────────────────────
││││││││││││││││││││┌ (::Base.GMP.var"#throw1#3")(y::Int64) @────────────────────
...
┌ neighbors(d::Int64) @ Main c:\git\SPHExample\example\TempRepoCLL.jl:39
│ runtime dispatch detected: (%48::CartesianIndices{N, R} where {N, R<:Tuple{Vararg{UnitRange{Int64}, N}}})[%52::Any]::Any

116 (possible) errors from this?

Kind regards

Is // intentional? That makes a Rational.

I just want to index from 1:half_of_array :slight_smile:

Then try integer division, ÷ as an infix operator or div as function notation.

1 Like

This function is type unstable because the type returned by CartesianIndices(...) carries the dimension (along with other things) as a type parameter and this cannot be inferred from the types of the function arguments.

1 Like

Thanks, using: half_length = length(n_) ÷ 2 now

@abraemer then maybe it is a bad idea to use CartesianIndices all together? Will always have to find against it then I suppose?

Kind regards

No. You just need to make its use typestable :slight_smile: E.g. you could pass in an array

function neighbors(array)
    n_ = CartesianIndices(array)
    n  = n_[begin:end÷2]
end
1 Like

The problem is the inability to infer the type of the output given the type of the input.

Right now the input type is Int but the output type is unclear since it depends on the value of the argument rather than its type.

  1. Rather than passing an Int you may want to pass a Val where the dimensionality is encoded in the type.

  2. Rather than using fill consider using ntuple with a Val argument.

I will edit this later with concrete examples.

First let’s look at type inferrence.

julia> @code_warntype neighbors(3)
MethodInstance for neighbors(::Int64)
  from neighbors(d::Int64) @ Main REPL[20]:1
Arguments
  #self#::Core.Const(neighbors)
  d::Int64                                                        Locals
  n::Any
  n_::CartesianIndices{N, R} where {N, R<:Tuple{Vararg{UnitRange{Int64}, N}}}
Body::Any
1 ─ %1  = (-1:1)::Core.Const(-1:1)
│   %2  = Main.fill(%1, d)::Vector{UnitRange{Int64}}
│   %3  = Core._apply_iterate(Base.iterate, Core.tuple, %2)::Tuple{Vararg{UnitRange{Int64}}}                                        │         (n_ = Main.CartesianIndices(%3))
│   %5  = n_::CartesianIndices{N, R} where {N, R<:Tuple{Vararg{UnitRange{Int64}, N}}}
│   %6  = Base.firstindex(n_)::Any
│   %7  = Base.lastindex(n_)::Integer
│   %8  = (%7 // 2)::Rational
│   %9  = (%6:%8)::Any
│   %10 = Base.getindex(%5, %9)::Any                              │         (n = %10)
└──       return %10

If you run this yourself you will see a lot of red text indicating type instability. Ultimately, Julia gave up figuring out the return type and just went with Any.

If we implement my suggestions, the situation will be greatly improved.

julia> function neighbors(v::Val{d}) where d
           n_ = CartesianIndices(ntuple(_->-1:1,v))
           return n_[begin:end÷2]
       end
neighbors (generic function with 2 methods)

julia> @code_warntype neighbors(Val(3))
MethodInstance for neighbors(::Val{3})
  from neighbors(v::Val{d}) where d @ Main REPL[28]:1
Static Parameters
  d = 3
Arguments
  #self#::Core.Const(neighbors)
  v::Core.Const(Val{3}())
Locals
  #5::var"#5#6"
  n_::CartesianIndices{3, Tuple{UnitRange{Int64}, UnitRange{Int64}, UnitRange{Int64}}}
Body::Vector{CartesianIndex{3}}
1 ─       (#5 = %new(Main.:(var"#5#6")))
│   %2  = #5::Core.Const(var"#5#6"())
│   %3  = Main.ntuple(%2, v)::Core.Const((-1:1, -1:1, -1:1))
│         (n_ = Main.CartesianIndices(%3))
│   %5  = n_::Core.Const(CartesianIndices((-1:1, -1:1, -1:1)))
│   %6  = Base.firstindex(n_::Core.Const(CartesianIndices((-1:1, -1:1, -1:1))))::Core.Const(1)
│   %7  = Base.lastindex(n_::Core.Const(CartesianIndices((-1:1, -1:1, -1:1))))::Core.Const(27)
│   %8  = (%7 ÷ 2)::Core.Const(13)
│   %9  = (%6:%8)::Core.Const(1:13)
│   %10 = Base.getindex(%5, %9)::Vector{CartesianIndex{3}}
└──       return %10

Now we see that Julia can figure out that if the input is of type Val{3} then the output will be of type Vector{CartesianIndex{3}}.

That’s better, but I am noticing that we have allocated a whole Vector.

julia> @time neighbors(Val(3))
  0.000008 seconds (1 allocation: 368 bytes)
13-element Vector{CartesianIndex{3}}:
 CartesianIndex(-1, -1, -1)
 CartesianIndex(0, -1, -1)
 CartesianIndex(1, -1, -1)
 CartesianIndex(-1, 0, -1)
 CartesianIndex(0, 0, -1)
 CartesianIndex(1, 0, -1)
 CartesianIndex(-1, 1, -1)
 CartesianIndex(0, 1, -1)
 CartesianIndex(1, 1, -1)
 CartesianIndex(-1, -1, 0)
 CartesianIndex(0, -1, 0)
 CartesianIndex(1, -1, 0)
 CartesianIndex(-1, 0, 0)

Instead we could just create a view of the CartesianIndices.

julia> function neighbors(v::Val{d}) where d
           n_ = CartesianIndices(ntuple(_->-1:1,v))
           return @view n_[begin:end÷2]
       end
neighbors (generic function with 2 methods)

julia> @time neighbors(Val(3))
  0.000003 seconds
13-element view(reshape(::CartesianIndices{3, Tuple{UnitRange{Int64}, UnitRange{Int64}, UnitRange{Int64}}}, 27), 1:13) with eltype CartesianIndex{3}:
 CartesianIndex(-1, -1, -1)
 CartesianIndex(0, -1, -1)
 CartesianIndex(1, -1, -1)
 CartesianIndex(-1, 0, -1)
 CartesianIndex(0, 0, -1)
 CartesianIndex(1, 0, -1)
 CartesianIndex(-1, 1, -1)
 CartesianIndex(0, 1, -1)
 CartesianIndex(1, 1, -1)
 CartesianIndex(-1, -1, 0)
 CartesianIndex(0, -1, 0)
 CartesianIndex(1, -1, 0)
 CartesianIndex(-1, 0, 0)

What the function returns acts the same as the Vector, but no memory is allocated!

julia> cis = neighbors(Val(3));

julia> cis[5]
CartesianIndex(0, 0, -1)

To maintain your original function signature, you can add the following method.

julia> neighbors(d::Int) = neighbors(Val(d))
neighbors (generic function with 2 methods)

julia> @code_warntype neighbors(3)
MethodInstance for neighbors(::Int64)
  from neighbors(d::Int64) @ Main REPL[41]:1
Arguments
  #self#::Core.Const(neighbors)
  d::Int64
Body::Any
1 ─ %1 = Main.Val(d)::Val
│   %2 = Main.neighbors(%1)::Any                                  └──      return %2

We see that type inferrence is still problematic. However something interesting occurs if we create a simple function wirh a known dimension.

julia> f() = neighbors(3)
f (generic function with 2 methods)

julia> @code_warntype f()
MethodInstance for f()
  from f() @ Main REPL[43]:1
Arguments
  #self#::Core.Const(f)
Body::SubArray{CartesianIndex{3}, 1, Base.ReshapedArray{CartesianIndex{3}, 1, CartesianIndices{3, Tuple{UnitRange{Int64}, UnitRange{Int64}, UnitRange{Int64}}}, Tuple{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}}}, Tuple{UnitRange{Int64}}, false}
1 ─ %1 = Main.neighbors(3)::Core.Const(CartesianIndex{3}[CartesianIndex(-1, -1, -1), CartesianIndex(0, -1, -1), CartesianIndex(1, -1, -1), CartesianIndex(-1, 0, -1), CartesianIndex(0, 0, -1), CartesianIndex(1, 0, -1), CartesianIndex(-1, 1, -1), CartesianIndex(0, 1, -1), CartesianIndex(1, 1, -1), CartesianIndex(-1, -1, 0), CartesianIndex(0, -1, 0), CartesianIndex(1, -1, 0), CartesianIndex(-1, 0, 0)])
└──      return %1

Here we have taken advantage of constant propagation. Julia figured out that 3 is a constant and was able to do type inferrence.

2 Likes

Thanks!

That seems to have entirely resolved it. I suppose there is not anyway to make the Val implicit, so that I can write neighbors(2) again?

First time I see Val and understand why it is useful at the same time. Thanks a ton!

I am fine with it being a bit confusing, just ease of personal use.

Kind regards

As you can see from the end of my edited post, we can add it, but we encounter the same issue as in the original case. The exception is if the integer is a constant or a type parameter.

Let’s say we have an image where we know the type. In this case we know thr array has e dimensions. That can also be propagated through.

julia> img = rand(0:9, (3,3,3))
3×3×3 Array{Int64, 3}:
[:, :, 1] =
 5  1  0
 7  5  8
 4  4  4

[:, :, 2] =
 6  1  8
 1  2  3
 2  9  4

[:, :, 3] =
 4  0  5
 1  0  2
 9  4  8

julia> neighbors(::AbstractArray{<: Any, N}) where N =
           neighbors(N)
neighbors (generic function with 3 methods)

julia> @code_warntype neighbors(img)
MethodInstance for neighbors(::Array{Int64, 3})
  from neighbors(::AbstractArray{<:Any, N}) where N @ Main REPL[52]:1
Static Parameters
  N = 3
Arguments
  #self#::Core.Const(neighbors)
  _::Array{Int64, 3}
Body::SubArray{CartesianIndex{3}, 1, Base.ReshapedArray{CartesianIndex{3}, 1, CartesianIndices{3, Tuple{UnitRange{Int64}, UnitRange{Int64}, UnitRange{Int64}}}, Tuple{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}}}, Tuple{UnitRange{Int64}}, false}
1 ─ %1 = Main.neighbors($(Expr(:static_parameter, 1)))::Core.Const(CartesianIndex{3}[CartesianIndex(-1, -1, -1), CartesianIndex(0, -1, -1), CartesianIndex(1, -1, -1), CartesianIndex(-1, 0, -1), CartesianIndex(0, 0, -1), CartesianIndex(1, 0, -1), CartesianIndex(-1, 1, -1), CartesianIndex(0, 1, -1), CartesianIndex(1, 1, -1), CartesianIndex(-1, -1, 0), CartesianIndex(0, -1, 0), CartesianIndex(1, -1, 0), CartesianIndex(-1, 0, 0)])
1 Like