-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: rewrite_sourceloc! function #22623
Conversation
base/loading.jl
Outdated
function propagate_sourceloc(sourceloc, ex) | ||
if ex isa Expr | ||
if ex.head == :macrocall | ||
ex.args[2] = sourceloc |
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.
Thinking about it, I'd better recurse into this as well.
base/loading.jl
Outdated
""" | ||
macro propagate_sourceloc(ex) | ||
:(propagate_sourceloc($(esc(:__source__)), $(esc(ex)))) | ||
end |
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.
This macro feels unnecessary to me - using the function form alone seems cleaner.
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.
Sure. How will we deal with 0.6 compatibility?
For context, I ported this utility from here: https://github.com/c42f/MicroLogging.jl/blob/e37dffcb7aeb9c581a27b897fa9d4fe3467d8b85/src/util.jl#L34 where I'm trying to support both 0.6 and 0.7; in 0.6 the __source__
variable isn't present which is the reason for the macro.
What's the sanest way to deal with getting a nop version of this into Compat
? I could add something to make the following work in 0.6, by just removing the function call. A bit messy!
@compat propagate_sourceloc(__source__, quote
@__LINE__
end)
Alternatively I could just move the @propagate_sourceloc
macro to Compat
...
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.
how about:
code = quote end
Compat.macros_have_sourceloc && propagate_sourceloc!(__source__, code)
return code
```
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.
Ok then. The few people who care about this (myself and two others?) can delete the small amount of mess once 0.7 is out - no need to make it super complicated.
838a519
to
213ab34
Compare
I changed some things as suggested and added some documentation. |
doc/src/stdlib/file.md
Outdated
@@ -50,6 +50,7 @@ Base.Filesystem.basename | |||
Base.@__FILE__ | |||
Base.@__DIR__ | |||
Base.@__LINE__ | |||
Base.propagate_sourceloc! |
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.
doesn't seem like the right manual section for this?
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.
Correct, however this is most related to @__LINE__
, @__FILE__
and @__DIR__
. Perhaps all these should be moved to another location. The location in the manual ("metaprogramming") seems much more sensible for these things, as they're all about introspection of the macro expansion process.
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.
How about moving all four of these to "doc/src/stdlib/base.md"?
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've moved these around - hopefully into a more coherent location in the stdlib docs.
base/exports.jl
Outdated
@@ -1214,6 +1214,7 @@ export | |||
@__FILE__, | |||
@__DIR__, | |||
@__LINE__, | |||
propagate_sourceloc!, |
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.
does this need to be exported?
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.
Good question. That depends on whether there's a distinction between "public API" and "exported function". I want this as a tool which can be used by packages, but it's also relatively obscure. So if there's a well defined category "public but not exported" this would fit in there, and we could remove the export.
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.
There are some things that are public but not exported, usually it's whether they are documented in a public way as if to be used qualified. Most of those are under more specific modules than Base though, like Profile. Could maybe move this to the Meta module?
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.
Ok, let's try this and see how it looks.
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.
cool, so if it's in Meta it probably shouldn't be re-exported from Base too
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.
Ah yes. I could have sworn I fixed that.
doc/src/manual/metaprogramming.md
Outdated
julia> dump(@__LOCATION__()) | ||
Tuple{Int64,String} | ||
1: Int64 1 | ||
2: String "REPL[2]" |
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.
will this pass when you run the doctests?
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.
It will now ;-)
Now moved to |
Looks like the travis failure is a timeout. |
Why base? |
base/meta.jl
Outdated
macro example() | ||
propagate_sourceloc!(__source__, | ||
quote | ||
@__LINE__ |
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 think I'm not understanding the purpose of this example, so I'm wary of, erhm, propagating it... If it's trying to solve c42f/MicroLogging.jl@f6db371#commitcomment-20846418 then why not interpolate __source__.line
? @__LINE__
is documented and implemented as an almost-literal (that's why we need the parser to insert it the value in the macrocall), so I think having this would be confusing.
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.
This is somewhat related to that old comment, but addresses the more general problem of wrapping macros which make use of __source__
, for example here:
If it were just @__LINE__
I was worried about, interpolating __source__.line
would be a better solution.
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.
That is, if package A
provides the macro
macro a()
quote
some_complicated_expression($(__source__.line))
end
end
And package B
wishes to wrap it -
macro b()
quote
# ...
@a
end
end
while preserving reporting of the source location, you either need a tool a bit like this, or to manually dig into the AST generated in @b
and rewrite the source location of the macro invocations contained within.
Because without this small tool, using |
Someone else should probably comment/approve. My thoughts are:
|
It would be great to find a more general way to handle this issue, e.g. during expansion, but given that AFAICT Clojure hasn't solved it either, I suspect it will be challenging. Also closely related: http://tratt.net/laurie/blog/entries/debugging_layers |
bd28452
to
78d1870
Compare
I've just wanted this again, so I've had occasion to come back to this and clean it up as suggested (the function is exported by As to whether this needs to be recursive - well obviously it doesn't, but it's a lot nicer for it to be recursive when the macro call or calls are nested deeply in the AST. I fully agree that having shared functions which generate |
The functionality 👍, that name though... Of course, I don't have any better ideas. |
Yes, the name is now quite a lot worse than it was when this PR was first submitted. I think I'll change the name to (Regarding length, both names are long but I think that's desirable for obscure and little used functionality.) |
78d1870
to
d97df51
Compare
Renamed. I had a think, but I'm all out of names which describe this operation clearly but succinctly. |
I assume the OSX Travis failures are spurious. It's hard to imagine how they could be related to the changes here. |
Could this be used to fix the following:
Here the source location info from the |
Yes, this is exactly what this function is for. (Though I'm just about to make |
Anyone remember: why didn't we ever merge this? |
A tool to propagate the __source__ variable from a macro to any macro calls in a given AST such that the inner macro calls are attributed the same line and file name.
Also find an improved location for __FILE__, __DIR__ and __LINE__ in the manual.
d97df51
to
7a6495c
Compare
I don't know why this wasn't merged; I think mainly the discussion went on long enough that I eventually forgot about it. Thanks for rebasing. I still use this trick occasionally, I just tend to write it out by hand. |
A tool to propagate the implicit
__source__
variable from a macro to anymacro calls in the generated AST.
This automates @vtjnash's trick from #21746 (comment) and makes it accessible to people who want to do the common task of making uses of
@__LINE__
inside a macro expand to the location of the macro caller, rather than a location inside the macro. (The trick is simple to use directly in some cases, but this tool makes it a lot easier to use if@__LINE__
is deeply embeeded in the AST.)An obvious question is whether this should propagate into nested macro calls when processing the AST. For now, I've not done this but perhaps I need to think a bit more about that.