As far as I understand, you're mostly right, except the structures bit. Disregarding that it is not possible to use several lifetime parameters yet, I see only one slight mistake: `s: MyStruct<'a>` does not imply that `s` variable has any specific lifetime. If it is a local variable, then it has 'lexical' lifetime; if it is a field in a structure, it has lifetime of the structure instance.
I guess what you meant is this: s: &'a MyStruct<'a> Here `s` pointer have lifetime 'a, as well as `s.r_int`. BTW, you came up with very nice math-like analogy, it helped me understand this thing even more. Thanks :) 2013/9/29 Gábor Lehel <[email protected]>: > 'self is not special in any way, except that the compiler has historical > baggage such that 'self is the only name it lets you use for a lifetime > parameter on a struct. But that's a bug. In the ideal platonic Rust in the > sky, you can have any number of lifetime parameters on a struct with > whatever names you prefer. > > The way I've found to think about lifetimes is that if you have: > > r_int: &'a int > > then 'a refers to a span of time (a scope, a lifetime) such that > lifetime_of(r_int) <= 'a <= lifetime_of(*r_int). (Where *r_int is intended > metaphorically to refer to the original object r_int was created from, not > the result of the *r_int expression itself.) So 'a is a kind of stand > between to ensure that r_int does not outlive the object it refers to. > > If you have > > fn foo<'a>(r_int: &'a int) -> &'a int > > then just like any other generics argument, the lifetime 'a is chosen by the > caller of `foo` (as inferred by the compiler). Typically the caller will > have an int object (i: int), then borrow a reference to it (r_int: &'a int = > &i) which it passes to `foo`, and then 'a will be the lifetime of the int. > `foo` will then have to return a reference to (an int that lives at least as > long). In practice this could either be the r_int it got as argument, or a > static int. > > `fn foo(arg: &int)` is shorthand for an anonymous lifetime parameter: `fn > foo<'a>(arg: &'a int)` > > In the return type position `fn foo() -> &int` is short for `fn foo<'a>() -> > &'a int`, meaning `foo` has to return a reference to (an int that lives as > long as any lifetime the caller could choose), which in practice means that > it has to be 'static. I believe you are or will be required to write > &'static explicitly in these cases to avoid confusion. > > With a struct it's not much different. > > s: MyStruct<'a> means lifetime_of(s) <= 'a > s: MyStruct<'a, 'b> means lifetime_of(s) <= 'a && lifetime_of(s) <= 'b > > If you have > > struct MyStruct<'self> { > r_int: &'self int > } > > s: MyStruct<'a> > > then lifetime_of(s) <= 'a && lifetime_of(s.r_int) <= 'a. (Which is trivial > because lifetime_of(s) == lifetime_of(s.r_int).) > > Basically, every object has a lifetime - from its creation to its > destruction - but a lifetime parameter or argument typically refers to the > lifetime of something else, which the object itself must not or does not > outlive. > > (Please yell at me if I got any of this wrong.) > > > > On Sun, Sep 29, 2013 at 5:23 PM, Oren Ben-Kiki <[email protected]> wrote: >> >> Ok, color me confused... perhaps there's somewhere that explains 'self on >> more detail? For example, _why_ does the example below not work without the >> explicit <'self>? It seems like it should. >> >> I have yet to truly understand the whole 'self thing. When I first read >> about lifetimes, my naive expectations were that: >> >> - Every struct has a 'self lifetime, which is basically "as long as this >> struct exists". It doesn't matter if I have a @ of the struct or a ~ of the >> struct or just a local variable with the struct... when the struct is >> dropped, the lifetime ends. >> >> - It follows there's no need to ever annotate structs as generic with a >> <'self> parameter - it always exists. >> >> - Any & in a struct is either &'self or &'static. A simple & should be >> &'self as that makes more sense (but if Rust wants me to be explicit, fine). >> >> This were my "least surprise" expectations, but things don't work this >> way... the problem is I don't have a simple mental model to replace the >> above with, so I struggle. What _is_ 'self, exactly? >> >> Isn't a function fn foo(&self) -> &T the same as returning a &'self T? Why >> would I want to say fn foo<'a>(&'a self) in the 1st place - 'a is "by >> definition" the same as 'self? How come David's Foo example fails the borrow >> check? >> >> Besides failing (my) "least surprise" expectations, the current rules also >> seem to be a "leaky abstraction". If I have a struct that holds a ComplexT >> member, it needs no <'self> parameter. If I then add a private member to my >> struct to hold some &'self PartOfT (say, cached access to an internal >> member), then boom, all uses of my struct now have to say <'self>, I can no >> longer put it in thread-local-storage, etc. I'd expect keeping these sort of >> cached borrowed pointers should be an internal implementation detail which >> does not affect the users of the struct at all. >> >> I suppose there's a good reason for all this, and a reasonable mental >> model I need to put in my head, but digging around the docs I didn't find >> one... Any hints would be appreciated :-) >> >> >> On Sun, Sep 29, 2013 at 5:42 PM, David Renshaw <[email protected]> >> wrote: >>> >>> Cool! I think that solution is much better than mine. >>> >>> > But I >>> > think that polluting traits-interfaces with lifetime annotation is >>> > wrong. Why the trait should have lifetime annotation? It is >>> > implementation detail. >>> >>> Just in case you want to see a case where it *does* make sense to put >>> a 'self lifetime in a trait definition, here is an example: >>> >>> https://gist.github.com/dwrensha/db919b8e130e9eb72f0f >>> _______________________________________________ >>> Rust-dev mailing list >>> [email protected] >>> https://mail.mozilla.org/listinfo/rust-dev >> >> >> >> _______________________________________________ >> Rust-dev mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/rust-dev >> > > > > -- > Your ship was destroyed in a monadic eruption. > > _______________________________________________ > Rust-dev mailing list > [email protected] > https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
