Differences with lifetime bounds between associated and free functions

โš“ Rust    ๐Ÿ“… 2025-07-13    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 2      

surdeus

Came across this issue today while trying to work with function pointers.

Consider an arbitrary struct with a lifetime parameter: struct Stackable<'gc> { ... }

I have a function pointer type defined like this: type NativeFunction = for<'gc> fn(Stackable<'gc>) -> Result<Option<Stackable<'gc>>, Error>. (As far as I understand it this is both the correct and only way of using the struct in a function pointer type, specifying that for any given lifetime, the function will consume a value and produce one with the same lifetime.)

The following free function conforms to this function pointer type: fn do_something<'gc>(value: Stackable<'gc>) -> Result<Option<Stackable<'gc>>, Error> { ... }

But an associated function on Stackable does not, even though it appears to have identical type:

impl<'gc> Stackable<'gc> {
    fn do_something(self) -> Result<Option<Stackable<'gc>>, Error> {
        todo!()
    }
}
error[E0308]: mismatched types
expected fn pointer `for<'gc> fn(Stackable<'gc>) -> Result<Option<Stackable<'gc>>, _>`
   found fn item `fn(Stackable<'_>) -> Result<Option<Stackable<'_>>, _> {Stackable::<'_>::do_something}`

I canโ€™t seem to understand the (variance?) issue here. To me it would appear that while the type dictates that the function needs to be callable for any given lifetime, the associated function is callable for any lifetime where the output lifetime matches the self lifetime, which in turn can be any given lifetime. Those two things are just two sides of the same coin to me.

Are there differences between lifetime parameters on types and functions?

Playground link

4 posts - 4 participants

Read full topic

๐Ÿท๏ธ rust_feed