Skip to content

Commit 6576bff

Browse files
aviateskc42f
andcommitted
Add inner err capture to MacroExpansionError
Information about this inner exception is currently completely lost, so without capturing it, there is no way for outside catchers to access this information. Co-authored-by: Claire Foster <[email protected]>
1 parent 13de283 commit 6576bff

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

src/macro_expansion.jl

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,19 @@ struct MacroExpansionError <: Exception
7878
context::Union{Nothing,MacroContext}
7979
ex::SyntaxTree
8080
msg::String
81+
"The source position relative to the node - may be `:begin` or `:end` or `:all`"
8182
position::Symbol
83+
"Error that occurred inside the macro function call (note that this may not be defined)"
84+
err
85+
MacroExpansionError(
86+
context::Union{Nothing,MacroContext}, ex::SyntaxTree, msg::AbstractString, position::Symbol
87+
) = new(context, ex, msg, position)
88+
MacroExpansionError(
89+
context::Union{Nothing,MacroContext}, ex::SyntaxTree, msg::AbstractString, position::Symbol,
90+
@nospecialize err
91+
) = new(context, ex, msg, position, err)
8292
end
8393

84-
"""
85-
`position` - the source position relative to the node - may be `:begin` or `:end` or `:all`
86-
"""
8794
function MacroExpansionError(ex::SyntaxTree, msg::AbstractString; position=:all)
8895
MacroExpansionError(nothing, ex, msg, position)
8996
end
@@ -126,8 +133,8 @@ function eval_macro_name(ctx::MacroExpansionContext, mctx::MacroContext, ex::Syn
126133
expr_form = to_lowered_expr(mod, ex5)
127134
try
128135
eval(mod, expr_form)
129-
catch
130-
throw(MacroExpansionError(mctx, ex, "Macro not found", :all))
136+
catch err
137+
throw(MacroExpansionError(mctx, ex, "Macro not found", :all, err))
131138
end
132139
end
133140

@@ -152,14 +159,16 @@ function expand_macro(ctx::MacroExpansionContext, ex::SyntaxTree)
152159
# TODO: Allow invoking old-style macros for compat
153160
invokelatest(macfunc, macro_args...)
154161
catch exc
155-
# TODO: Using rethrow() is kinda ugh. Is there a way to avoid it?
156-
# NOTE: Although currently rethrow() is necessary to allow outside catchers to access full stacktrace information
157162
if exc isa MacroExpansionError
158163
# Add context to the error.
159-
rethrow(MacroExpansionError(mctx, exc.ex, exc.msg, exc.position))
164+
newexc = isdefined(exc, :err) ?
165+
MacroExpansionError(mctx, exc.ex, exc.msg, exc.position, exc.err) :
166+
MacroExpansionError(mctx, exc.ex, exc.msg, exc.position)
160167
else
161-
rethrow(MacroExpansionError(mctx, ex, "Error expanding macro", :all))
168+
newexc = MacroExpansionError(mctx, ex, "Error expanding macro", :all, exc)
162169
end
170+
# TODO: We can delete this rethrow when we move to AST-based error propagation.
171+
rethrow(newexc)
163172
end
164173

165174
if expanded isa SyntaxTree

test/macros.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ let (err, st) = try
156156
e, stacktrace(catch_backtrace())
157157
end
158158
@test err isa JuliaLowering.MacroExpansionError
159+
@test isdefined(err, :err)
159160
# Check that `catch_backtrace` can capture the stacktrace of the macro functions
160161
@test any(sf->sf.func===:f_throw, st)
161162
@test any(sf->sf.func===Symbol("@m_throw"), st)
@@ -168,6 +169,7 @@ let res = try
168169
end
169170
@test res isa JuliaLowering.MacroExpansionError
170171
@test res.msg == "Macro not found"
172+
@test isdefined(res, :err) && res.err isa UndefVarError
171173
end
172174

173175
include("ccall_demo.jl")
@@ -179,6 +181,7 @@ let (err, st) = try
179181
end
180182
@test err isa JuliaLowering.MacroExpansionError
181183
@test err.msg == "Expected a return type annotation like `::T`"
184+
@test !isdefined(err, :err)
182185
# Check that `catch_backtrace` can capture the stacktrace of the macro function
183186
@test any(sf->sf.func===:ccall_macro_parse, st)
184187
end

0 commit comments

Comments
 (0)