Generic functions and their pointer uniquness

Playing around with generics, I noticed that generic functions always generate unique pointers for each instantiation:

fn test_trait<T>() {
}

fn main() {
    let first: fn () = test_trait::<usize>;
    let second: fn () = test_trait::<String>;
    let third: fn () = test_trait::<usize>;
    println!("{:?} | {:?} | {:?}", first, second, third);
    assert_eq!(first, third);
    assert_ne!(first, second);
}

But I don't think the behavior is documented anywhere so that I could rely on it.
Is anyone aware if the behavior is documented when it comes to function address?

I don't think that you can rely on this, because when I tried it on release mode they all had the same address

Damn, you're right.
I guess it is up to compiler so that it would be possible to optimize.
This is unfortunate

It's interesting that, if the function really does something depending on the type, the addresses will be different even in release: Rust Playground This is understandable, since compiler must generate code for every of them, so maybe in this case the difference might be reliable.

LLVM doesn't even know that they come from the same generic source when it deduplicates them... which means even completely distinct functions can end up sharing the same code location if the optimizer chooses.

1 Like

Yeah, but it is completely unreliable because it is up to compiler to decide.
So you cannot really rely on it.

Pointer uniqueness of function is non-deterministic actually.

In my opinion, PartialEq and Hash shouldn't be implemented for function pointers, but it's here, and it cannot be removed now. Also, because those are implementations, you cannot even deprecate those (see `#[deprecated]` does nothing if placed on an impl item. · Issue #39935 · rust-lang/rust · GitHub). That said, most programs don't compare function pointers (I think?), so this isn't that big of a deal.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.