Conversation

I've been working on a Rust project with a friend and I swear he's the best tester for compiler error messages. Today, when he wanted to add a generic type to an enum that already had a lifetime, he wrote: enum Foo<'a><T> { ... } The compiler was not ready for this case! 😂 /1
6
96
If you think about it, this is a perfectly logical thing to do. Lifetimes and generics are separate things, so why not put them in separate angle-bracketed sections? Sure you get it once you see <'a, T> for the first time, but I don't blame my friend at all for trying this out /2
2
43
I've been trying to call out this teaching failure mode for years now lifetime parameters *are* generic parameters! that's why they are in the same angle brackets! you add them to data types *expressly* to generalize over any lifetime (otherwise you're stuck with only 'static)
3
4
teaching lifetimes like they're different leads to many unnecessary wrong assumptions like when people think you add lifetimes to a struct to relate the "lifetime of the struct" with references inside: that's not a thing, and it's a sign that something went wrong in teaching!
2
1
yeah we could totally have used regular type generics, it just requires changing &'a T syntax and maybe a few other things here and there
2
3
it makes even more sense when we stop talking about "lifetimes" and more about "origins" like in ' talk from last year because what's important to track is how a borrow was created, everything else derives from it if you think about it... that could include Box<T>!
3
4
now think about how much better than C++'s weak attempts at borrow-like checking you could do with such a system and Haskell-like inference, in a higher-level language! "ownership polymorphism" that defaults to GC or w/e but implicitly supports Rust-like allocation schemes
2
1
struct Foo<T> { data: &[T], count: &mut usize, next: Option<&mut Foo<T>>, } // automatically transformed to: struct Foo<'a, 'b, 'c, T> { data: &'a [T], count: &'b mut usize, next: Option<&'c mut Foo<'a, 'b, 'c, T>>, } then you just infer fn signatures!
1
1