Well, that’s fairly obvious. But I don’t really understand why—the order of operations is not what I would expect.
The expression foo(x::A) = x
shouldn’t throw an UndefVarError
until the expression is actually evaluated. For example, this does not throw an error:
julia> if false
foo(x::A) = x
else
1
end
1
Interestingly, this leads to an even more perverse example with @test_throws
:
julia> @test_throws UndefVarError begin
if false
foo(x::A) = x
else
1
end
end
ERROR: UndefVarError: `A` not defined
Or a similar example with @test
:
julia> @test begin
if false
foo(x::A) = x
true
else
true
end
end
ERROR: UndefVarError: `A` not defined
My understanding is that the @test_throws
macro should expand before foo(x::A) = x
is evaluated, and the @test_throws
macro expands to some kind of try-catch block. Note that a basic try-catch block works as expected:
julia> try
foo(x::A) = x
catch
println("hello world")
end
hello world
So, let’s take a closer look at what @test_throws
expands to. After re-typesetting the output of @macroexpand
in my editor to make it more readable, the output of @macroexpand @test_throws UndefVarError f(x::A)=x
is
quote
Test.do_test_throws(
begin
try
Test.Returned(
$(Expr(:(=), :(foo(x::A)), quote x end)),
Test.nothing,
$(QuoteNode(:(#= REPL[8]:1 =#)))
)
catch var"#24#_e"
if UndefVarError != Test.InterruptException && var"#24#_e" isa Test.InterruptException
Test.rethrow()
end
Test.Threw(var"#24#_e", Test.nothing, $(QuoteNode(:(#= REPL[8]:1 =#))))
end
end,
$(QuoteNode(:(foo(x::A) = begin
x
end))),
UndefVarError
)
end
But I don’t know enough about Test
internals to be able to interpret that…