Would it make sense to have special enums that can assist runtime dispatch by creating specialized methods for Val?
julia> macro dispatch_enum(basetype, args...)
name = basetype isa Expr ? basetype.args[1] : basetype
esc(quote
@enum($((basetype, args...)...))
@generated Base.Val(var"#"::$name) = let ifex(enum)=:(if $enum≡var"#"; Val{$enum}() end),
enums = collect(values(Base.Enums.Enums.namemap($name))), ret = ifex(enums[1]), expr = ret
for enum = enums[2:end]; expr = last(push!(expr.args, ifex(enum))) end
expr.head, expr.args = expr.args[end].head, expr.args[end].args
ret
end
nothing
end)
end
@dispatch_enum (macro with 1 method)
julia> @dispatch_enum foo a b c
julia> methods(Val)
# 2 methods for type constructor:
[1] Val(var"#"::foo)
@ Main REPL[1]:5
[2] Val(x)
@ essentials.jl:801
julia> @code_warntype Val(a)
MethodInstance for Val(::foo)
from Val(var"#"::foo) @ Main REPL[1]:5
Arguments
#self#::Type{Val}
#::foo
Body::Union{Val{a}, Val{c}, Val{b}}
1 ─ %1 = (Main.a ≡ #)::Bool
└── goto #3 if not %1
2 ─ %3 = Core.apply_type(Main.Val, Main.a)::Core.Const(Val{a})
│ %4 = (%3)()::Core.Const(Val{a}())
└── return %4
3 ─ %6 = (Main.c ≡ #)::Bool
└── goto #5 if not %6
4 ─ %8 = Core.apply_type(Main.Val, Main.c)::Core.Const(Val{c})
│ %9 = (%8)()::Core.Const(Val{c}())
└── return %9
5 ─ %11 = Core.apply_type(Main.Val, Main.b)::Core.Const(Val{b})
│ %12 = (%11)()::Core.Const(Val{b}())
└── return %12