'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

Reply via email to