Lifetime notation


I do not like about lifetime syntax mainly the unclosed apostrophe. Using a different character like a pipe (<|a, T>) or the at sign(<@a, T>). These are not commonly used in rust and they do not need to get closed.


@pyfisch, I don’t see “unclosed apostrophes” as a problem. After all, don't contains unclosed apostrophes.

| is the “bit-wise or” operator and part of the closure syntax. I cannot exactly call this “not commonly used”.

@ is used in patterns in Rust, and many other languages use it for “meta” things like macros/annotations/decorators, so it is not a good sigil for lifetimes.

EDIT: wording.


@CloudiDust: They just do not work well with editors. Yes it is of course true that | and @ are already used in Rust but these occurences have a different place than lifetimes.


Random example from whatever my browser’s address bar suggested. While I think making 'xyz, 'tcx any longer would be a mistake, it is already noisy enough that we might put everything in the compiler in methods on the appropriate context types, so it might not be as much of an issue then.

Also, which highlighters is 'a confusing, exactly? Lots of languages have lots of odd corners and most highlighters can deal with crazier things than almost anything in Rust. There’s some counter-examples which make me sad, but have technical reasons. They also don’t happen to be lifetime notation.


They just do not work well with editors.

A bit more work than only supporting 'a', yes, but I don’t consider this much of a problem, given that disambiguating 'a' and 'a is still quite straightforward. Also note that the | sigil also comes in “two favors”, one needs closing (the closure sigil), and one needs not (the bit-wise or operator)…


I’m a newcomer to the language. And I’m really excited about Rust’s approach of making a memory safe language without the need of garbage collection. However, after looking through the initial documentation I bumped into something that shocked me to say the least. The lifetime notation is really difficult to read. I get that it is there because the compiler needs it so far. But, will there be a time when it is not needed anymore? Will Rust be able to elide it everywhere at some point? Or is it something that might change its syntax but will always be there?


When I looked at Lisp for the first time, I was overwhelmed with parens. I thought “hey, how come these people live with all these brackets?” After a while I get used to them and now they seem quite natural thing.

Many experienced programmers just forget about all difficulties of learning new languages. Remeber yourself when you first saw C++. Didn’t it look like a random scratches on a wall for you? It’s OK to have difficulties when learning new concepts, it’s natural and human.

What I want to say, new things looking like new is good, because the language doesn’t lie to you pretending new things to be well known ones. It’s not a problem, it’s a reason to learn.


There is a couple of places where it will always be needed. At least:

  1. unsafe code. When binding to C functions the compiler can’t deduce until when things are valid, because the information simply isn’t there.
  2. Generics with lifetime constraints, because there the constraints govern the implementation and not the other way around; and traits don’t have any implementation to deduce from yet anyway.


Ok, I see. However, mixing generic arguments and lifetime names within angle brackets makes it difficult to read. I think that it would be easier to read it if Rust kept only generic arguments within angle brackets and used another notation (e.g.: square brackets) to declare lifetime names. That way it would be more consistent: angle brackets mean generics, the other notation means lifetime names. And it would make also easier the transition from other languages, because in most of them only generics are declared within angle brackets (i.e.: C++, Java, …)


In several ways, lifetimes are just another kind of generic parameter (using ‘kind’ along the lines “higher kinded types”)—one could regard the relationship as somewhat similar to hypothetical integer generics vs. normal type parameters. A function/type with lifetime parameters is can be said to be generic over those lifetimes.

I suspect that separating lifetimes from types may be more confusing, since it divorces the similar concepts, and forces people to remember which syntax to use when (even if people don’t like <...> at least we’re uniform at the moment). On the other hand, I could easily be wrong.


I agree with you that lifetimes are like another kind of high level information. But IMHO, as they can be applied on the generic arguments, I think that it would be clearer if they were declared first on their own. For example, having the following declaration:

struct Reader<'a, T: 'a> {
    position: uint,
    data: &'a [T]

I think that it would be clearer something like the following:

struct Reader<'a><T:'a> {
    position: uint,
    data: &'a [T]

struct Reader['a]<T:'a> {
    position: uint,
    data: &'a [T]

But this is just my opinion after being in contact with the language only for a tiny amount of time, coming from a C++, Java background.