- 
                Notifications
    You must be signed in to change notification settings 
- Fork 9
Allow outside catchers to see full stacktrace information of macro expansion #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow outside catchers to see full stacktrace information of macro expansion #23
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current design with lowering throwing errors, I find it a little odd to store the backtrace inside the exception itself, as that's also available at the catch site outside of JuliaLowering.
But I'm ok with this because we should probably move to an error propagation model where we don't throw any exception from lowering, but instead propagate errors via AST nodes of kind K"error" (allowing for partial lowering of broken ASTs).  And in that case we will need something similar to what you've done here.
| Oh, please also add a test of both catch error code paths before merging :) (I added you as a collaborator so you can merge this when it's ready) | 
| @@ -1,6 +1,8 @@ | |||
| @testset "macros" begin | |||
| module macros | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this change for the following reasons (along with the corresponding change on runtests.jl):
- To prevent name collisions with other test files
- To enable test/macros.jlto be executed as a standalone script from the command line
Having said that, this creates a different style from other test files, so if you don't like this, I'd be happy to revert it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really mind this change.  But if you first include("test/utils.jl") most (all?) of the non-IR test/blah.jl should be able to be included individually at the REPL? This is how I run tests though it's admittedly slightly clunky.
| 
 Hmm, that's certainly true. If we change  JuliaLowering.jl/src/macro_expansion.jl Lines 155 to 166 in 2dd53bf 
 invokelatest(macfunc, macro_args...)even when caught outside. That might be cleaner and simpler implementation-wise, although we may end up implementing a similar stacktrace-capturing mechanism in the future anyway. Your comment just above also mentions wanting to avoidrethrow(), so I'd like to ask for your judgment on this. | 
`MacroExpansionError` has good information about error location, but
does not preserve information about the error raised by user macros
beyond the error message itself. Such information is very useful for
tooling like language servers, and stacktraces are particularly
important.
This commit adds a `stacktrace::Vector{Base.StackTraces.StackFrame}`
field to `MacroExpansionError`. New macro definitions still call the
`MacroExpansionError(ex::SyntaxTree, msg::AbstractString;
position=:all)` constructor, which internally calls `stacktrace(...)`,
so the user-facing interface remains unchanged. Additionally,
`scrub_expand_macro_stacktrace` is implemented to automatically trim
information about JL internal functions that are not useful to users.
    2dd53bf    to
    07cd3e6      
    Compare
  
    | 
 I've implemented a way to avoid capturing stack traces by using  | 
07cd3e6    to
    fbdca4d      
    Compare
  
    | Let's proceed with using  | 
…acktrace Allow outside catchers to see full stacktrace information of macro expansion.
| 
 Just as a heads up, we've been exploring this kind of use case for loading in Base too: JuliaLang/julia#55816 (comment) I need to find a minute to re-visit my stack trace changes so that it's possible to do what that comment talks about it, but the general idea is to be able to efficiently record a "marker" in the catch backtrace, so that you can slice out the relevant bits later (without having to eagerly unwind and then pattern match on the symbolized stack trace) | 
| invokelatest(macfunc, macro_args...) | ||
| catch exc | ||
| # TODO: Using rethrow() is kinda ugh. Is there a way to avoid it? | ||
| # NOTE: Although currently rethrow() is necessary to allow outside catchers to access full stacktrace information | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. I think we'll resolve this by just not throwing at all here, once we move to propagating errors differently.
| 
 I think this is ok for now. As I noted above, I think we'll just delete the  | 
…acktrace Allow outside catchers to see full stacktrace information of macro expansion.
MacroExpansionErrorhas good information about error location, but does not preserve information about the error raised by user macros beyond the error message itself. Such information is very useful for tooling like language servers, and stacktraces are particularly important.This commit adds a
stacktrace::Vector{Base.StackTraces.StackFrame}field toMacroExpansionError. New macro definitions still call theMacroExpansionError(ex::SyntaxTree, msg::AbstractString; position=:all)constructor, which internally callsstacktrace(...), so the user-facing interface remains unchanged.Additionally,
scrub_expand_macro_stacktraceis implemented to automatically trim information about JL internal functions that are not useful to users.