Reputation: 5075
In C and C++ you can get the name of the currently executing function through the __func__
macro with C99 & C++11 and ___FUNCTION___
for MSVC.
Is there an equivalent of this in Rust?
Example of __func__
in C:
#include "stdio.h"
void funny_hello() {
printf ("Hello from %s\n", __func__);
}
int main() {
funny_hello();
}
Outputs Hello from funny_hello
.
Upvotes: 53
Views: 19576
Reputation: 60137
You can hack one together with std::any::type_name
.
macro_rules! function {
() => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
let name = type_name_of(f);
name.strip_suffix("::f").unwrap()
}}
}
Note that this gives a full pathname, so my::path::my_func
instead of just my_func
. A demo is available.
Upvotes: 55
Reputation: 31
Adding to Alexis's answer there is a more idiomatic way to write this macro that also works inside rust async functions. Otherwise you will get {{closure}}
in async function instead of real function name.
macro_rules! function {
() => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
type_name_of(f)
.rsplit("::")
.find(|&part| part != "f" && part != "{{closure}}")
.expect("Short function name")
}};
}
Upvotes: 3
Reputation: 2516
While there's a lack of official support, there's the stdext crate (also mentioned in the RFC issue) that makes it easy to use.
use stdext::function_name;
fn foo() {
println!("{}", function_name!());
}
This includes module/trait names, like ::module::Trait::function
if any.
If you only care about the name and not its entire path, you could do something like this for trait methods (keep in mind that there is runtime overhead for this, you may want to limit it with, e.g. OnceCell):
let fn_name = function_name!()
.rsplit_once(':')
.expect("could not parse function name")
.1;
Upvotes: 0
Reputation: 3598
It appears that function_name
crate will do this.
https://docs.rs/function_name/latest/function_name/
The example from the docs is
use ::function_name::named;
#[named]
fn my_super_duper_function ()
{
assert_eq!(
function_name!(),
"my_super_duper_function",
);
}
I am not involved with the project and have not actually tried it yet.
Upvotes: 10
Reputation: 165
Adding to Veedrac's answer, you can get the function's name without its full path by adding this:
macro_rules! function {
() => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
let name = type_name_of(f);
// Find and cut the rest of the path
match &name[..name.len() - 3].rfind(':') {
Some(pos) => &name[pos + 1..name.len() - 3],
None => &name[..name.len() - 3],
}
}};
}
You will get my_func
instead of my::path::my_func
for example.
Upvotes: 12
Reputation: 37836
There was an RFC about this, but it was never agreed upon or implemented.
The rationale for its absence:
"In general I don't think any of us have given an inordinate amount of thought to these "debugging related" macros in terms of long term stability. Most of them seem fairly harmless, but committing to provide all of them for all Rust programs forever is a strong commitment to make. We may want to briefly consider the story of these macros in conjunction with considering adding this new macro."
Maybe Rust will have something comparable in the future,
but for now you will need to rely on your own tagging.
side note: __FUNCTION__
is non standard, __func__
exists in C99 / C++11.
Upvotes: 32