Does Rust have anything similar to CallerMembrerName in C#

Viewed 52

I'd like to know the name of the function that called my function in Rust.

In C# there's CallerMemberName attribute which tells the compiler to replace the value of a string argument to which it's applied with the name of the caller.

Does Rust have anything like that?

1 Answers

I don't know of a compile time solution, but you can use the backtrace functionality to resolve it at runtime.

use backtrace::Backtrace;

fn caller_name_slow() -> Option<String> {
    let backtrace = Backtrace::new();
    let symbolname = backtrace.frames().get(2)?.symbols().first()?.name();
    symbolname.map(|s| format!("{:#?}", s))
}

fn caller_name_fast() -> Option<String> {
    let mut count = 0;
    let mut result = None;

    backtrace::trace({
        |frame| {
            count += 1;
            if count == 5 {
                // Resolve this instruction pointer to a symbol name
                backtrace::resolve_frame(frame, |symbol| {
                    if let Some(name) = symbol.name() {
                        result = Some(format!("{:#?}", name));
                    }
                });
                false
            } else {
                true // keep going to the next frame
            }
        }
    });

    result
}

fn my_function() {
    println!("I got called by '{}'.", caller_name_slow().unwrap());
    println!("I got called by '{}'.", caller_name_fast().unwrap());
}

fn main() {
    my_function();
}
I got called by 'rust_tmp::main'.
I got called by 'rust_tmp::main'.

Note, however, that his is unreliable. The amount of stack frames we have to go up differs between targets and release/debug (due to inlining). For example, on my machine, in release I had to modify count == 5 to count == 2.

Related