# How does Julia invoke constructors with overlapping constraints

**URL:** https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243
**Category:** New to Julia
**Created:** [November 30, 2025, 8:41pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243 "2025-11-30T20:41:13Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)
#### Post date: [November 30, 2025, 8:41pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/1 "2025-11-30T20:41:13Z")

</div>

Hello, I am playing with constructors, but seems, that Julia allows to have constructor with overlapping constrains N.

```julia
using StaticArrays: SizedVector

mutable struct Context{TYPE_VAR_STACK <: Union{UInt8, UInt16}, N <:Union{UInt8, UInt16}}
    stack::SizedVector
    index::N 

    # Constructor constraint for N <:UInt8
    function Context(stack_type::Type{T}, stack_length::N, def_stack_val=eltype(stack_type)(0),) where {T <: Union{UInt8, UInt16}, N <: Union{UInt8}}
        
        println("ctor UInt8")
        # StaticArrays pkg doesn't allow to have its Size in different types than Int
        size = Int(stack_length)
        new{T, N}(SizedVector{size}(fill(def_stack_val, size)), size)
        
    end

    # More general constructor for N <:Union{UInt8 and UInt16}
    function Context(stack_type::Type{T}, stack_length::N, def_stack_val=eltype(stack_type)(0),) where {T <: Union{UInt8, UInt16}, N <: Union{UInt8, UInt16}}
        # StaticArrays pkg doesn't allow to have its Size in different types than Int
        size = Int(stack_length)
        new{T, N}(SizedVector{size}(fill(def_stack_val, size)), size)
        
    end

end

# More specific
julia> Context(UInt16, UInt8(100))
ctor UInt8
Context{UInt16, UInt8}(UInt16[0, 0, 0, 0, 0, 0, 0, 0, 0, 0 … 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 100)
# More specific
julia> Context(UInt8, UInt8(100))
ctor UInt8
Context{UInt8, UInt8}(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0 … 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 100)

# More generic
julia> Context(UInt8, UInt16(100))
Context{UInt8, UInt16}(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0 … 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 100)

```

and methods

```julia-auto
julia> methods(Context)
# 4 methods for type constructor:
 [1] Context(stack_type::Type{T}, stack_length::N) where {T<:Union{UInt16, UInt8}, N<:UInt8}
     @ ~/devel/julia/bf/bf.jl:8
 [2] Context(stack_type::Type{T}, stack_length::N, def_stack_val) where {T<:Union{UInt16, UInt8}, N<:UInt8}
     @ ~/devel/julia/bf/bf.jl:8
 [3] Context(stack_type::Type{T}, stack_length::N, def_stack_val) where {T<:Union{UInt16, UInt8}, N<:Union{UInt16, UInt8}}
     @ ~/devel/julia/bf/bf.jl:18
 [4] Context(stack_type::Type{T}, stack_length::N) where {T<:Union{UInt16, UInt8}, N<:Union{UInt16, UInt8}}
     @ ~/devel/julia/bf/bf.jl:18

```

I have several question:

1. Is there some kind of internal mechanism, that uses more specific constructor?
2. Is there possibility to call more general constructor?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 30, 2025, 8:45pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/2 "2025-11-30T20:45:06Z")

</div>

1. The same way as for any other function multiple dispatch/method specificity [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#methods)
2. `invoke`

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [December 1, 2025, 11:34am UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/3 "2025-12-01T11:34:16Z")

</div>

Just a slightly off-topic comment. Your struct has an abstract field `stack::SizedVector`, i.e. a `SizedVector` without a size and type. This is a performance-killer, since the compiler must generate code for dynamic dispatch when you access the field `stack` in a `Context`-object. It’s perfectly ok, but the struct shouldn’t be used in performance critical loops.

---

<div class="post-metadata">

### Author: ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)
#### Post date: [December 1, 2025, 4:41pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/4 "2025-12-01T16:41:44Z")

</div>

Thank you!

How does the StaticArrays/SizedVector works?

1. approach:

```julia-auto
#include <stdio.h>
#include <stdlib.h>
int main(void) {
   
  some_type *SizedVector = malloc(sizeof(some_type) * N) 
    
  return EXIT_SUCCESS;
}

```

1. approach is basically pointer to some heap memory, and keep reference.

2. approach

```julia-auto
#include <stdio.h>
#include <stdlib.h>
int main(void) {

  some_type Sized_Vector[N];
    
  return EXIT_SUCCESS;
}

```

1. Approach, using some macros magic I created sized SizedVector on stack.

I believe, that 2. approach is correct, but I am not sure, I read the code but it slightly cryptic for me (I am just learning Julia for 4th day).

Additional question:  
How can I solve that I don’t know the type (T) and size (N) for SizedVector?  
Shall I try to use upper boundaries e.g. typemax(UInt16)?

Edit:  
Added changed code, but I was out of luck to figure out how does to say SizedVector in the struct correct type.  
I tried this, but seems that without luck:

```julia-auto
using StaticArrays: SizedVector

mutable struct Context{TYPE_VAR_STACK <: Union{UInt8, UInt16}, N <:Union{UInt8, UInt16}, SIZE <:Val{Int64}}
    stack::SizedVector{SIZE, TYPE_VAR_STACK}
    index::N 

    function Context(stack_type::Type{T}, stack_length::N, def_stack_val::T=eltype(stack_type)(0)) where {T <: Union{UInt8, UInt16}, N <: Union{UInt8, UInt16}}
        # StaticArrays pkg doesn't allow to have its Size in different types than Int
        size = Int64(stack_length)
        stack = SizedVector{size, stack_type}(fill(def_stack_val, size))
        new{T, N, size}(stack, firstindex(stack))
    end
end

```

---

<div class="post-metadata">

### Author: ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)
#### Post date: [December 1, 2025, 8:30pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/5 "2025-12-01T20:30:21Z")

</div>

Seems, that I was able to do it, but I don’t know if this approach is correct, not sure how many types will be crated based on SIZE.

```julia-auto
mutable struct Context{TYPE_VAR_STACK <: Union{UInt8, UInt16}, N <:Union{UInt8, UInt16}, SIZE}
    stack::SizedVector{SIZE, TYPE_VAR_STACK}
    index::N 

    function Context(stack_type::Type{T}, stack_length::N, def_stack_val::T=eltype(stack_type)(0)) where {T <: Union{UInt8, UInt16}, N <: Union{UInt8, UInt16}}
        # StaticArrays pkg doesn't allow to have its Size in different types than Int
        size = Int64(stack_length)
        stack = SizedVector{size, stack_type}(fill(def_stack_val, size))
        return new{T, N, size}(stack, firstindex(stack))
    end
end

julia> sdd = Context(UInt16, UInt16(1200), UInt16(33))
Context{UInt16, UInt16, 1200}(UInt16[0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021 … 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021], 0x0001)

```

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [December 1, 2025, 8:35pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/6 "2025-12-01T20:35:02Z")

</div>

> [@RCh](#):
>
> How can I solve that I don’t know the type (T) and size (N) for SizedVector?

The `SizedVector` actual has three parameters.

One way to handle this transparently is to parametrize the stack type:

```julia-auto
mutable struct Context{TYPE_VAR_STACK <: Union{UInt8, UInt16}, N <:Union{UInt8, UInt16}, VTYPE}
    stack::VTYPE
    index::N 

    function Context(stack_type::Type{T}, stack_length::N, def_stack_val::T=eltype(stack_type)(0)) where {T <: Union{UInt8, UInt16}, N <: Union{UInt8, UInt16}}
        # StaticArrays pkg doesn't allow to have its Size in different types than Int
        size = Int64(stack_length)
        stack = SizedVector{size, stack_type}(fill(def_stack_val, size))
        new{T, N, typeof(stack)}(stack, firstindex(stack))
    end
end

```

However, there’s a subtle problem here. In the constructor, you create a type from a value,  
i.e. the value of `size`, i.e. of the argument `stack_length` is put into the type domain when you use it as a type parameter. If you do something like

```julia-auto
function f(N, ...)
    ctx = Context(UInt8, N)
    while ...
        <use ctx>
    end
end

```

The compiler does not know what type `ctx` is when it compiles the `while` loop, because the compiler does not know the value of `N`, only its type (presumably an integer of some type). So it can’t infer the full type of `ctx`, and may resort to dynamic dispatch.

Unless it’s important to have the size of the `stack` in `Context` in the type domain, I would suggest to use an ordinary `Vector` instead. The `SizedVector` is anyway just a thin wrapper around the `Vector` you create with `fill`:

```julia-auto
julia> ctx = Context(UInt8, UInt16(1024));
julia> dump(ctx)
Context{UInt8, UInt16, SizedVector{1024, UInt8, Vector{UInt8}}}
  stack: SizedVector{1024, UInt8, Vector{UInt8}}
    data: Array{UInt8}((1024,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 … 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  index: UInt16 0x0001

```

---

<div class="post-metadata">

### Author: ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)
#### Post date: [December 1, 2025, 9:00pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/7 "2025-12-01T21:00:15Z")

</div>

Thank you!

One more question:  
Here I used SIZE and passed integer, I feel that it is wrong:

> [@How does Julia invoke constructors with overlapping constraints](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/5):
>
> Seems, that I was able to do it, but I don’t know if this approach is correct, not sure how many types will be crated based on SIZE. mutable struct Context{TYPE\_VAR\_STACK \<: Union{UInt8, UInt16}, N \<:Union{UInt8, UInt16}, SIZE} stack::SizedVector{SIZE, TYPE\_VAR\_STACK} index::N function Context(stack\_type::Type{T}, stack\_length::N, def\_stack\_val::T=eltype(stack\_type)(0)) where {T \<: Union{UInt8, UInt16}, N \<: Union{UInt8, UInt16}} # StaticArrays pkg doesn't allow to have it…

It is wrong because for each of the size, the compiler creates its own type somewhere?  
e.g

```julia-auto
julia> dump(Context(UInt16, UInt16(1200), UInt16(33)))
Context{UInt16, UInt16, 1200}
  stack: SizedVector{1200, UInt16, Vector{UInt16}}
    data: Array{UInt16}((1200,)) UInt16[0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021 … 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021]
  index: UInt16 0x0001

julia> dump(Context(UInt16, UInt16(1), UInt16(33)))
Context{UInt16, UInt16, 1}
  stack: SizedVector{1, UInt16, Vector{UInt16}}
    data: Array{UInt16}((1,)) UInt16[0x0021]
  index: UInt16 0x0001

```

For Size=1200 there will be some type  
For Size=1 there is another  
?

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [December 1, 2025, 9:49pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/8 "2025-12-01T21:49:37Z")

</div>

> [@RCh](#):
>
> For Size=1200 there will be some type  
> For Size=1 there is another  
> ?

Yes, but it’s not wrong, it works. It depends on what you’re using this for. When you call a function, it is compiled for the exact type of the actual arguments. So with many different values of `Size` you will compile a lot. If, in addition, the size isn’t known at compile time, the compiler may not even know which particular method to call, so even a simple access like `ctx.stack[14]` may end up with a dynamic dispatch (a runtime method lookup), both for `getproperty` (the `.stack` part), and `getindex` (the `[14]` indexing part).

In some cases, in particular with small `StaticVector`s with compile time sizes (e.g. 3d vectors and matrices, or other small (say \< 100) fixed sizes), the compiler gets many opportunities to optimize, using the stack instead of the heap, unroll loops etc. So then it can very beneficial.

Since `SizedVector` really is just a wrapper around a `Vector`, it’s mostly useful for static dispatch on the vector length, I don’t think there are any big optimization opportunities beyond that. I.e. you may write `f(x::SizedVector{1000)) = ...`, and another method for `f(x::SizedVector{2000}) = ...`.

Btw, there is also a low-level fixed size `Memory` struct, without the length in the type domain (so no dispatch on size), which works much like a fixed size `Vector`.

```julia-auto
julia> v = Memory{UInt8}(undef, 100)
100-element Memory{UInt8}:
...

```

Indeed, `Vector` is a wrapper around a `Memory` struct. In practice, a `Vector` works just as well and has more functionality, the wrapper is usually optimized away by the compiler, so there’s usually little to gain by using `Memory`.

---

<div class="post-metadata">

### Author: ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)
#### Post date: [December 2, 2025, 6:53pm UTC](https://discourse.julialang.org/t/how-does-julia-invoke-constructors-with-overlapping-constraints/134243/9 "2025-12-02T18:53:46Z")

</div>

Thank you!
