Val type is type unstable?

Hello, should I be afraid of ::Val{_A} where _A in this situation?

f(x, y, ::Val{:x}) = x
f(x, y, ::Val{:y}) = y
f(x, y, s :: Symbol) = f(x, y, Val(s))
@code_warntype f(1,2,:x)

Variables
  #self#::Core.Const(f)
  x::Int64
  y::Int64
  s::Symbol

Body::Int64
1 ─      nothing
│   %2 = Main.Val(s)::Val{_A} where _A
│   %3 = Main.f(x, y, %2)::Int64
└──      return %3

Does that mean all my code which uses Val is type unstable?

1 Like

Not necessarily. Val(s) itself returns different types for different values of s and is by definition type unstable. Val{:x} on the other hand is a specific type.

In your example the return type of f is type stable but the internal type instability would need a (relatively slow) dynamic dispatch to resolve, unless the function is specialized by constant propagation. If you use Val(:x), i.e. with a literal argument, you should see that you get a correctly inferred return type, for example.

Addendum: This is a better illustration of specialization by constant propagation for your example:

julia> g(x, y) = f(x, y, :x)
g (generic function with 1 method)

julia> @code_warntype g(1, 2)
Variables
  #self#::Core.Const(g)
  x::Int64
  y::Int64

Body::Int64
1 ─ %1 = Main.f(x, y, :x)::Int64
└──      return %1
3 Likes

Thanks for this answer!