# Why would \`\<:\` in Unions for keyword arguments create allocations

**URL:** <https://discourse.julialang.org/t/why-would-in-unions-for-keyword-arguments-create-allocations/112390>\
**Category:** General Usage\
**Created:** [April 1, 2024, 9:49pm UTC](https://discourse.julialang.org/t/why-would-in-unions-for-keyword-arguments-create-allocations/112390 "2024-04-01T21:49:16Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![mattsignorelli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattsignorelli/32/221502_2.png) [@mattsignorelli](https://discourse.julialang.org/u/mattsignorelli)\
**Post date:** [April 1, 2024, 9:49pm UTC](https://discourse.julialang.org/t/why-would-in-unions-for-keyword-arguments-create-allocations/112390/1 "2024-04-01T21:49:16Z")

</div>

Take this MWE function which simply returns the argument at the specified index `idx` or `y` in the vector `v`:

```julia
function foo(v::Vector{Int}, idx::Union{Nothing,Int}=nothing; y::Union{Nothing,Integer}=nothing)
  if !xor(isnothing(idx), isnothing(y))
  error("invalid arguments")
  end

  if isnothing(y)
    return v[idx]
  else
    return v[y]
  end
end

```

With Benchmark tools we see:

```julia-repl
julia> a = [1,2,3,4,5,6,7,8,9,10];

julia> @btime foo($a,1);
  1.375 ns (0 allocations: 0 bytes)

julia> @btime foo($a,y=1);
  1.333 ns (0 allocations: 0 bytes)

```

No surprises here, zero allocations. Now let’s make one tiny change and let the keyword argument type be `Union{Nothing, <:Integer}` instead of `Union{Nothing, Integer}`, so:

```julia
function foo2(v::Vector{Int}, idx::Union{Nothing,Int}=nothing; y::Union{Nothing,<:Integer}=nothing)
  if !xor(isnothing(idx), isnothing(y))
  error("invalid arguments")
  end

  if isnothing(y)
    return v[idx]
  else
    return v[y]
  end
end

```

Now we see with `foo2`:

```julia-repl
julia> @btime foo2($a,1);
  1.333 ns (0 allocations: 0 bytes)

julia> @btime foo2($a,y=1);
  184.793 ns (3 allocations: 96 bytes)

```

Why would there be allocations by having the `<:` in vs not for the keyword argument? I do not see similar behavior when changing the non-keyword argument to `<:Integer`?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 2, 2024, 12:28am UTC](https://discourse.julialang.org/t/why-would-in-unions-for-keyword-arguments-create-allocations/112390/2 "2024-04-02T00:28:13Z")

</div>

I think that’s a bug, note that with `Union{Nothing, T} where {T<:Integer}` the function does not allocate, and AFAIU, it should be the same. Here a reduced example:

```julia-repl
julia> foo(v; y::Union{Nothing,<:Integer}=nothing) = isnothing(y) ? v[1] : v[y]
foo (generic function with 1 method)

julia> @btime foo($[1,2,3];y=1);
  286.996 ns (3 allocations: 96 bytes)

julia> foo(v; y::Union{Nothing,Integer}=nothing) = isnothing(y) ? v[1] : v[y]
foo (generic function with 1 method)

julia> @btime foo($[1,2,3];y=1);
  2.609 ns (0 allocations: 0 bytes)

julia> foo(v; y::Union{Nothing,T}=nothing) where {T<:Integer} = isnothing(y) ? v[1] : v[y]
foo (generic function with 1 method)

julia> @btime foo($[1,2,3];y=1);
  3.002 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![mattsignorelli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattsignorelli/32/221502_2.png) [@mattsignorelli](https://discourse.julialang.org/u/mattsignorelli)\
**Post date:** [April 2, 2024, 12:56am UTC](https://discourse.julialang.org/t/why-would-in-unions-for-keyword-arguments-create-allocations/112390/3 "2024-04-02T00:56:50Z")

</div>

[Reported](https://github.com/JuliaLang/julia/issues/53917)
