Does function know its name?

fn main ()  {
    fn1 () ;
}
fn fn1 () {
    println! ( " Hello,my name is...  { : ? } ",   " I don know(((  "  )  ;
}
1 Like

I'm assuming that you are referring to the ability to display, or perhaps store, the name of an arbitrary function so that you can use the name as you would a variable.

Support for this technique is made possible through what is known as "runtime reflection". It exists in some programming languages to varying degrees. There is also a concept known as "compile-time reflection", which the reflect crate appears to make work through the usage of macros.

Rust doesn't support runtime reflection. It would be quite difficult, but (perhaps) not impossible, to do what you're trying to do. If you are really interested in doing this, however, you could try implementing something fairly simple such as a container that stores the functions that exist in your program and provides an API to access them as needed.

For example, a naive approach could resemble something like a VTable that contains function pointers mapped to their associated names with the names represented in memory as strings (or whatever type you prefer). This implementation would behave in a similar way as a global HashMap or similar data structure.

I'm sure someone else will come along and give a more thorough explanation. Hopefully this helps!

1 Like

It has been suggested a few times, but hasn't come to be so far.

There is a crate or two that supply the name, but I don't know anything about them so use your own judgement.

3 Likes

You can use std::any::type_name() and the fact that each function is also its own zero-sized type to get the name of a function as long as it's being passed around directly (e.g. by name or via generics) instead of being coerced to a fn() pointer.

fn main() {
    println!("The main function is called {:?}", type_name_of_val(&main));
}

fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
    std::any::type_name::<T>()
}

(playground)

I don't think this is very useful though, seeing as you need to already have a variable/item containing the function and can't just say "what's the current function?" like __func__ in C.

3 Likes

module_path in std - Rust and line in std - Rust are the closest thing, AFAIK

1 Like

You can do this to some extent at runtime with the backtrace crate (Rust Playground):

use backtrace::Backtrace;

#[inline(never)]
fn caller_name() -> Option<String> {
    let backtrace = Backtrace::new();
    let symbol = backtrace
        .frames()
        .iter()
        .flat_map(|frame| frame.symbols())
        .nth(1)?;
    let name = format!("{}", symbol.name()?);
    let name = name.rsplit_once("::")?.0.to_string();
    Some(name)
}

But note that it will return None if the final binary is stripped of its debug symbols.

2 Likes

Should be able to do this with #[track_caller] and std::panic::Location::caller()

Edit: damn, no, sorry: misread the example. You can get the file name and location, but it is manually providing the failed function name itself in the example.

1 Like