Skip to content

Commit fedc5c5

Browse files
authored
Merge pull request #27 from c42f/avi/capture-inner-macro-expansion-error
Add inner `err` capture to `MacroExpansionError`
2 parents 13de283 + eacacd7 commit fedc5c5

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

src/macro_expansion.jl

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,16 @@ 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 (`nothing` if no inner exception)"
84+
err
85+
MacroExpansionError(
86+
context::Union{Nothing,MacroContext}, ex::SyntaxTree, msg::AbstractString, position::Symbol,
87+
@nospecialize err = nothing
88+
) = new(context, ex, msg, position, err)
8289
end
8390

84-
"""
85-
`position` - the source position relative to the node - may be `:begin` or `:end` or `:all`
86-
"""
8791
function MacroExpansionError(ex::SyntaxTree, msg::AbstractString; position=:all)
8892
MacroExpansionError(nothing, ex, msg, position)
8993
end
@@ -126,8 +130,8 @@ function eval_macro_name(ctx::MacroExpansionContext, mctx::MacroContext, ex::Syn
126130
expr_form = to_lowered_expr(mod, ex5)
127131
try
128132
eval(mod, expr_form)
129-
catch
130-
throw(MacroExpansionError(mctx, ex, "Macro not found", :all))
133+
catch err
134+
throw(MacroExpansionError(mctx, ex, "Macro not found", :all, err))
131135
end
132136
end
133137

@@ -152,14 +156,14 @@ function expand_macro(ctx::MacroExpansionContext, ex::SyntaxTree)
152156
# TODO: Allow invoking old-style macros for compat
153157
invokelatest(macfunc, macro_args...)
154158
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
157159
if exc isa MacroExpansionError
158160
# Add context to the error.
159-
rethrow(MacroExpansionError(mctx, exc.ex, exc.msg, exc.position))
161+
newexc = MacroExpansionError(mctx, exc.ex, exc.msg, exc.position, exc.err)
160162
else
161-
rethrow(MacroExpansionError(mctx, ex, "Error expanding macro", :all))
163+
newexc = MacroExpansionError(mctx, ex, "Error expanding macro", :all, exc)
162164
end
165+
# TODO: We can delete this rethrow when we move to AST-based error propagation.
166+
rethrow(newexc)
163167
end
164168

165169
if expanded isa SyntaxTree

test/macros.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,20 @@ let (err, st) = try
156156
e, stacktrace(catch_backtrace())
157157
end
158158
@test err isa JuliaLowering.MacroExpansionError
159+
@test !isnothing(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)
162163
end
163164

164-
let res = try
165+
let err = try
165166
JuliaLowering.include_string(test_mod, "_never_exist = @m_not_exist 42")
166167
catch e
167168
e
168169
end
169-
@test res isa JuliaLowering.MacroExpansionError
170-
@test res.msg == "Macro not found"
170+
@test err isa JuliaLowering.MacroExpansionError
171+
@test err.msg == "Macro not found"
172+
@test err.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 isnothing(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)