Are lifetimes part of the type?

Viewed 80

The various documentation, such as the types reference, does not go into the relationship between types and lifetimes in detail. This made me wonder if lifetimes are part of types themselves or if they are just compiler hints that are erased before monomorphization occurs.

Given the following example:

fn example<'a, 'b>(a: &'a str, b: &'b str) {
    struct Foo<T> {
        t: T,
    }

    let bar = Foo { t: a };
    let baz = Foo { t: b };
}

Are bar and baz both of the same type with lifetimes erased (i.e. Foo<&str>) and sharing one monomorphized copy, or are they two distinct types Foo<&'a str> and Foo<&'b str> where the lifetime is part of the type?

And as a side note: is the type inference algorithm documented anywhere for how T received its final type in each case?

1 Answers

There are a couple of different issues here. For values, every type is erased. Rust compiles to native, and on a native architecture, Foo and every other type is just a sequence of bytes. There's no reflection like in Java that can recover even a partial type.

The monomorphization issue comes up with generic functions. Specifically,

fn foo<T>(x: T) -> T {
  x
}

This function will generate a different (native) function for each T, so foo(0 as i32) and foo("ABC") are actually calling distinct functions. In that sense, lifetimes are erased before monomorphization occurs, so if we have a function that looks like

fn foo<'a, T>(x: &'a T) -> &'a T {
  x
}

then only differing T parameters will result in different functions. If only the lifetimes differ, new functions will not be generated.

Related