Open pnkfelix opened 8 years ago
there's an open RFC for the function name: #1719
C# has a nice implementation of this: They have the nameof()
-operator, which returns the name of the type, method or variable you put into it. https://msdn.microsoft.com/de-de/library/dn986596.aspx
Not really. C#'s nameof
is "dumb" and returns literally whatever you type into it, only as a string. With generics, nameof(T)
returns T
and with a function, you'd have to type the function name each time (i.e. log!("Entering {}", nameof(this_function_name)
), whereas with a proper __function__
macro, that can be turned into a copy-and-paste friendly log!("Entering {}", fn_name!())
or similar.
Hi all,
I've implemented this feature over current Rust beta in:
https://github.com/da-x/rust/tree/function-macro
I have not included type parameters in the output string because it's not very useful for me. But I did include the nesting, though (a::b..).
This is my first time hacking on Rust's compiler, so bear with me that it may be ugly/inefficient, etc.
@da-x quick question: https://github.com/rust-lang/rfcs/pull/1719#issuecomment-245224914
EDIT: sounds like line numbers would be a good way to differentiate two same-named inner functions that are at the same nest-level.
@xftroxgpx another case to consider are two calls to function!()
within in the exact same function - therefore I think that no assumption of uniqueness should be made on the result of multiple function!()
invocations within a crate. So my opinion is that anyone needing uniqueness should tuple the result of function!()
with line!()
and friends.
So, What's the status of it?
Now that I am actually using my implementation in the logging system I am writing, I fixed some bugs there. Updated my branch (also rebased ontop 1.25.0). Before, the names from methods functions, default implementation of trait methods, and the name of the struct for which the method is implemented, were all missing.
Hi all,
Although the RFC is not fully formed, I submitted an implementation as a pull request so we can have a working reference implementation that may assist in promoting the discussion and maybe reach some conclusions how to move this forward.
Nominating for discussion; this has been around for a while, and it seems completely reasonable. I'd like to see this myself.
We discussed this (and https://github.com/rust-lang/rust/pull/49820) in the @rust-lang/lang meeting. There was full consensus that Rust should have a macro to return the function name. Procedurally, this needs to have an RFC (or revive the old one), and an implementation with tests and a feature gate. Other open questions include:
function!
already; may need better macro module handling (https://github.com/rust-lang/rust/issues/35896). For instance, we need a test to make sure that a macro using this function!
doesn't break if expanded in a file that defines its own macro named function!
.Not breaking if people have a macro named function!
Isn't that something that can happen with new Rust versions? The release notes could communicate it right? As long as they build their existing project with a version of Rust prior to the release with the new macro they should be fine? I guess it's more of an issue with using crates? Is crates.io able to inspect each crates src for such usage in some way?
What happens if you use this in a closure? Should it identify the closure somehow, or the containing named function, or both?
Presumably I get the file name and line that the closure was declared in, like a source map. Since the closure has no name(is using the function parameter name useful?) it might make sense to use the named function it was declared in(not file and function name that is taking the closure as a parameter, eg .map()
). I think you can also define a variable to place a closure in too. my_function():closure
perhaps?
This is quite a pain for anything related to logging and error reporting. Any chance of this making it into 2018 edition? A nightly? Anything?
- Bikeshedding the name ;)
- Not breaking if people have a macro named function! already
Call the built-in one __super_secret_macro_never_use_it__
and publish unofficial function-name
crate defining function!
which wraps the built-in. You get the point. This is something what can be done right now.
- What happens if you use this in a closure? Should it identify the closure somehow, or the containing named function, or both?
First, you need not guarantee the stability of this macro output. Second, you can make it compatible with a backtrace/unwinding output, i.e. output whatever panic!
would output. Compiler has all the corner cases implemented already. Give the user "hello_world::main::{{closure}}"
and let him decide how to split/trim it.
Any chance of this making it into 2018 edition?
Unfortunately, not. It would take too much time to do all the steps required to ship this on stable by the time the edition goes into feature freeze.
Unfortunately, tracking this for some one just doing a search seems to be rather difficult having so many issues related to this:
Eg: https://github.com/rust-lang/rfcs/pull/466 https://github.com/rust-lang/rfcs/pull/1719 https://github.com/rust-lang/rust/issues/35651 https://github.com/rust-lang/rust/pull/49820
(.. and probably quite a few more, that left me jumping back and forth)
If this is indeed the latest issue, I think it would be quite useful to have a section in the main post, for older references and make sure it's indicated that this is the latest one, and RFC links if any. It's rather funny, for some relatively simple, it's leaving behind so much "discussion cruft".
Following the ongoing effort in Rust 2018 to make macros first class citizens like other items, perhaps it is worth to consider having function!
be provided from a path, i.e. std::macros::function
, so that the actual name would matter less? That way, slog
and other logging crates could refer to std::macros::function
directly without worrying if a user already defined function!
locally.
Any traction on this? I am getting tired of adding let fn_name = "func" everywhere...
I'd like to see this revived as well.
@pnkfelix Do you have time to write up an RFC? It shouldn't be an especially complex RFC, and with the current state of macro scoping I think it's reasonable to add a new macro and expect that it won't break people who have their own macros.
I think if you pick a reasonable name we can hopefully avoid bikeshedding it.
The only remaining bikeshedding I know of: how should it interact with closures? I would argue for expanding to the name of the lexically containing named function, as closures don't have any meaningful name.
A closure's name should (bikeshed) probably be the name of the creating function with a line number or other identifier stuck on to the end, my_func#234
.
I definitely have functions that end up holding more than one closure.
@Lokathor Interesting. I would expect most uses of this to go along with usage of the file and line (and possibly column) macros. How would you feel about just my_func::(closure)
if that assumption holds true?
Small data point: rustc-demangle
uses my_func::{closure#0}
for the #2603 mangling format.
Other parts of rustc, including the legacy mangling format, haven't switched to that yet, AFAIK, but maybe they should? (it's a detail I meant to change and I've forgotten about since, TBH)
I wouldn't normally think to pair func_name!() with line!() and file!() because usually when i want it I want "emergency println debugging" and i'm just throwing in a few printers and i delete them once i've sorted out what's wrong.
For example, in an emulator i've been working on the past bit i've regularly wanted to just kinda keep a mild log of the control flow when adding a new part into the mix, so something like
fn draw_to_bitmap(&self, bitmap: &mut Bitmap) {
will get a temporary println!("draw_to_bitmap");
put at the top of the function, and then once i'm sure things are fine I just remove it entirely.
Another thing that I often wanted this sort of thing for is a way to format the function's name into an error message, "func: message"
and similar.
That said, i have used file! and line! before, and i'm not opposed to having them help disambiguate things as well, i just wouldn't normally think to use them right away.
If my_func::{closure#0}
is already somewhere in the compiler, we should just adopt that if it's easy to do so. That's readable enough.
(I assume that the particular format of this macro would be "debug string info, subject to change in the future", and that we're not going to be tied to the format we pick here forever.)
(I assume that the particular format of this macro would be "debug string info, subject to change in the future", and that we're not going to be tied to the format we pick here forever.)
Agreed.
Alright, let's assume for now that closures use the same internal format that they use elsewhere, and we can always change that later.
@pnkfelix @Lokathor Does one of you have time to turn this into an RFC? It doesn't need much, just an explanation of the use case (debugging) and the behavior (function name as a static string, best-effort for closures).
uh, sure
Proper PR opened https://github.com/rust-lang/rfcs/pull/2818
RFC #466 was closed back in the days before we had a protocol for opening up follow-up issues to use to gather links to related discussion.
The idea is that we already have some macros (
file!
andline!
) that are useful for reporting source code context, and it might be nice to expand that collection with macros that include other information, such as the current function name, which I believe was the suggestion of thefunction!
macro that was at one point described in RFC #466 (whose draft contents have now been lost, apparently).Here is my attempt to retrieve the Motivation from that original draft text. (I don't think we need the detailed design in the description of an issue like this.)