# Method for \`Base.length\` on a \`const\` type alias crashes julia

**URL:** <https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169>\
**Category:** General Usage\
**Tags:** question, base, methods\
**Created:** [August 14, 2024, 9:15am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169 "2024-08-14T09:15:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![kunzaatko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kunzaatko/32/25153_2.png) [@kunzaatko](https://discourse.julialang.org/u/kunzaatko)\
**Post date:** [August 14, 2024, 9:15am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/1 "2024-08-14T09:15:12Z")

</div>

Julia is crashing when I try to define a `Base.length` method on a `const` type alias.

```julia-repl
julia> import Base: length

julia> const A{N} = NTuple{N, Int64}
Tuple{Vararg{Int64, N}} where N

julia> length(a::A) = prod(a)

```

After this, julia does not throw any errors but crashes when I try to execute any other code. Is this something wrong with my code or is it a bug?  
I managed to get the `stderr` output during the crash:

```txt
fatal: error thrown and no exception handler available.
BoundsError(a=(), i=1)
ijl_bounds_error_int at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/rtutils.c:187
ijl_get_nth_field at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/datatype.c:1569
ijl_get_nth_field_checked at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/datatype.c:1614
getindex at ./tuple.jl:31 [inlined]
iterate at ./tuple.jl:72 [inlined]
iterate at ./tuple.jl:72
unknown function (ip: 0x7c96086e7c75)
iterate at ./iterators.jl:298
isempty at ./essentials.jl:957
schedule at ./task.jl:849
unknown function (ip: 0x7c96086e9e60)
notify at ./condition.jl:154 [inlined]
#notify#646 at ./condition.jl:148 [inlined]
notify at ./condition.jl:148 [inlined]
notify at ./condition.jl:148 [inlined]
task_done_hook at ./task.jl:658
unknown function (ip: 0x7c96086e9e05)
_jl_invoke at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:2895 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:3077
jl_apply at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/julia.h:1982 [inlined]
jl_finish_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:320
start_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:1249
e[2 qschedule: Task not runnable
atexit hook threw an error: ErrorException("schedule: Task not runnable")
error at ./error.jl:35
#schedule#673 at ./task.jl:851
schedule at ./task.jl:849 [inlined]
uv_writecb_task at ./stream.jl:1166
unknown function (ip: 0x7c96086ec31c)
uv__write_callbacks at /workspace/srcdir/libuv/src/unix/stream.c:959
uv__stream_io at /workspace/srcdir/libuv/src/unix/stream.c:1294
uv__run_pending at /workspace/srcdir/libuv/src/unix/core.c:804
uv_run at /workspace/srcdir/libuv/src/unix/core.c:392
ijl_task_get_next at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/partr.c:478
poptask at ./task.jl:985
wait at ./task.jl:994
uv_write at ./stream.jl:1048
unsafe_write at ./stream.jl:1120
write at ./strings/io.jl:248 [inlined]
print at ./strings/io.jl:250
unknown function (ip: 0x7c96086ecce9)
_jl_invoke at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:2895 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:3077
showerror at ./errorshow.jl:151
unknown function (ip: 0x7c96086ed179)
_jl_invoke at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:2895 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:3077
_atexit at ./initdefs.jl:431
unknown function (ip: 0x7c96086ea827)
_jl_invoke at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:2895 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:3077
jl_apply at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/julia.h:1982 [inlined]
ijl_atexit_hook at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/init.c:280
ijl_exit at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/init.c:207
ijl_no_exc_handler at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:699
jl_finish_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:323
start_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:1249
error in running finalizer: BoundsError(a=(), i=1)
ijl_bounds_error_int at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/rtutils.c:187
ijl_get_nth_field at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/datatype.c:1569
ijl_get_nth_field_checked at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/datatype.c:1614
getindex at ./tuple.jl:31 [inlined]
iterate at ./tuple.jl:72 [inlined]
iterate at ./tuple.jl:72
unknown function (ip: 0x7c96086e7c75)
iterate at ./iterators.jl:298
isempty at ./essentials.jl:957
schedule at ./task.jl:849
notify at ./condition.jl:154 [inlined]
#notify#646 at ./condition.jl:148 [inlined]
notify at ./condition.jl:148 [inlined]
uvfinalize at ./asyncevent.jl:205
unknown function (ip: 0x7c96086ed7c5)
_jl_invoke at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:2895 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gf.c:3077
run_finalizer at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gc.c:318
jl_gc_run_finalizers_in_list at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gc.c:408
run_finalizers at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/gc.c:454
ijl_atexit_hook at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/init.c:299
ijl_exit at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/init.c:207
ijl_no_exc_handler at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:699
jl_finish_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:323
start_task at /cache/build/builder-amdci4-0/julialang/julia-release-1-dot-10/src/task.c:1249

```

Yet a similar definition of the method for `intersect` works as intended

```julia-repl
julia> import Base: intersect

julia> const A{N} = NTuple{N, Int64}
Tuple{Vararg{Int64, N}} where N

julia> intersect(a::A{N}, as::A{N}...) where {N} = prod.([a, as...])
intersect (generic function with 43 methods)

julia> intersect((5,4,5,4), (4,5,3,3))
2-element Vector{Int64}:
 400
 180

```

**version:** `julia version 1.10.4`

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [August 14, 2024, 9:29am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/2 "2024-08-14T09:29:07Z")

</div>

You are redefining the length of a `Tuple` and this is causing your problems. Your `length(a::A)` is the same as trying to redefine `length(a::NTuple{N, Int})`. This is just one of the many possible consequences of type piracy.

If you want to do definitions like this, you’d need to define a wrapper struct over the `Tuple` instead of trying to use a type alias.

---

<div class="post-metadata">

**Author:** ![kunzaatko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kunzaatko/32/25153_2.png) [@kunzaatko](https://discourse.julialang.org/u/kunzaatko)\
**Post date:** [August 14, 2024, 9:46am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/3 "2024-08-14T09:46:47Z")

</div>

Thank you!  
So if I understand correctly, the second method definition is also type piracy and I should avoid both of them, right?  
The solution to this would be to define it as a new type?

```julia
struct A{N}
    a::NTuple{N, Int64}
end

```

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [August 14, 2024, 9:48am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/4 "2024-08-14T09:48:12Z")

</div>

Yeah, that’s exactly right.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [August 14, 2024, 2:36pm UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/5 "2024-08-14T14:36:09Z")

</div>

The other alternative is to keep using the `Tuple` type but use a function other than `Base.length`. For example, `MyModule.length` or `length_as_axes` or whatever thing you’re actually trying to do here. The method you’re defining doesn’t match the usage of `Base.length` anyway, so there isn’t much benefit to it sharing the method table.

Although from your example, it appears you’re trying to encode something specific with this tuple so it probably makes the most sense to make a custom type. As a total shot in the dark, it seems you might be looking for something like [`CartesianIndices`](https://docs.julialang.org/en/v1/base/arrays/#Base.IteratorsMD.CartesianIndices) ([helpful blog post](https://julialang.org/blog/2016/02/iteration/)):

```julia-repl
julia> length(CartesianIndices((2,3,1))) # a 2x3x1 array of indices
6

julia> collect(CartesianIndices((2,3,1))) # what this looks like when iterated
2×3×1 Array{CartesianIndex{3}, 3}:
[:, :, 1] =
 CartesianIndex(1, 1, 1) CartesianIndex(1, 2, 1) CartesianIndex(1, 3, 1)
 CartesianIndex(2, 1, 1) CartesianIndex(2, 2, 1) CartesianIndex(2, 3, 1)

```

---

<div class="post-metadata">

**Author:** ![kunzaatko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kunzaatko/32/25153_2.png) [@kunzaatko](https://discourse.julialang.org/u/kunzaatko)\
**Post date:** [August 14, 2024, 3:58pm UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/6 "2024-08-14T15:58:45Z")

</div>

Thank you! This was actually a toy example and my use is different. This is my actual code:

```julia
struct Window{N}
    win::NTuple{N,ClosedInterval{Int}}
end
Base.length(w::Window{N}) where {N} = prod(d -> d.right - d.left + 1, w.win)

```

And `length` is then used for normalizing a function on the `Window`. Are there any reasons to make it a different function altogether? Perhaps some interface for which this does not quite match the intended original meaning (or even meaning it has for other types) of the function `length`?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 14, 2024, 4:10pm UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/7 "2024-08-14T16:10:25Z")

</div>

That does sound very much like `CartesianIndices`! They similarly select rectangular windows of integer indexes. Instead of a `ClosedInterval{Int}`, they’re `AbstractUnitRange{Int}`s. But the functionality sounds quite similar.

Either way, you’d really only want to use `Base.length` if you’re describing the number of elements that could be generated by iteration.

---

<div class="post-metadata">

**Author:** ![kunzaatko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kunzaatko/32/25153_2.png) [@kunzaatko](https://discourse.julialang.org/u/kunzaatko)\
**Post date:** [August 15, 2024, 8:36am UTC](https://discourse.julialang.org/t/method-for-base-length-on-a-const-type-alias-crashes-julia/118169/8 "2024-08-15T08:36:05Z")

</div>

This is a great tip! I just checked and both the methods that I showed on `Window` are defined on `CartesianIndices`.

```julia-repl
julia> CartesianIndices((4:10, 6:10, 3:7)) |> length
175

julia> intersect(CartesianIndices((4:10, 6:10, 3:7)), CartesianIndices((6:10, 7:8, 5:15)))
CartesianIndices((6:10, 7:8, 5:7))

```

So to summarize my takeaway… I could use the `CartesianIndices` type and define additional functions on it which I need. The limitation is that if I would like to define a method of a function in another package, that would be an external function on an external type, thus type piracy. A third alternative is to define a type as a thin wrapper over the `CartesianIndices` type and not try to reinvent the wheel.
