I don’t have a satisfactory answer for you @Benjia, though maybe someone else does.
Poking around, it seems that the method by which julia does type assertion on keyword arguments is very different from those in positional arguments and it’s not exactly easy to find by standard reflection tools. Here’s how you could conceivably do it though:
First, let’s look at what actually happens when you call a function with a keyword argument (it’s more subtle than you might guess!)
julia> f(x; y::Int) = x * y
f (generic function with 1 method)
julia> g() = f(1; y=3.0)
g (generic function with 1 method)
julia> @code_lowered g()
CodeInfo(
1 ─ %1 = (:y,)
│ %2 = Core.apply_type(Core.NamedTuple, %1)
│ %3 = Core.tuple(3.0)
│ %4 = (%2)(%3)
│ %5 = Core.kwfunc(Main.f)
│ %6 = (%5)(%4, Main.f, 1)
└── return %6
)
Okay, so what this says is that f(1; y=3.0)
is actually doing
Core.kwfunc(f)(NamedTuple{(:y,)}((3,)), f, 1)
Okay, so let’s take a peek inside this call and see what it does:
julia> @code_lowered Core.kwfunc(f)(NamedTuple{(:y,)}((3,)), f, 1)
CodeInfo(
1 ── %1 = Base.haskey(@_2, :y)
└─── goto #6 if not %1
2 ── %3 = Base.getindex(@_2, :y)
│ %4 = %3 isa Main.Int
└─── goto #4 if not %4
3 ── goto #5
4 ── %7 = %new(Core.TypeError, Symbol("keyword argument"), :y, Main.Int, %3)
└─── Core.throw(%7)
5 ┄─ @_6 = %3
└─── goto #7
6 ── %11 = Core.UndefKeywordError(:y)
└─── @_6 = Core.throw(%11)
7 ┄─ y = @_6
│ %14 = (:y,)
│ %15 = Core.apply_type(Core.NamedTuple, %14)
│ %16 = Base.structdiff(@_2, %15)
│ %17 = Base.pairs(%16)
│ %18 = Base.isempty(%17)
└─── goto #9 if not %18
8 ── goto #10
9 ── Base.kwerr(@_2, @_3, x)
10 ┄ %22 = Main.:(var"#f#69")(y, @_3, x)
└─── return %22
)
Yikes. If you spend enough time staring at this, you will see that what this says is that it checks in y
isa Int
:
2 ── %3 = Base.getindex(@_2, :y)
│ %4 = %3 isa Main.Int
└─── goto #4 if not %4
3 ── goto #5
and if it’s not an int, then it goes to
4 ── %7 = %new(Core.TypeError, Symbol("keyword argument"), :y, Main.Int, %3)
└─── Core.throw(%7)
which is saying ‘throw an error’. I’m not sure if there’s an automated way to discover this.