Thanks for the explanation. You said two key points:
- 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.
And:
- '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.

So, 'self is indeed very far from what I thought (hoped) it would be.

Taking these together, do I read this right as saying there is no way
whatsoever to say:

struct Foo {
    bar: Bar,
    baz: &'i-live-as-long-as-the-foo-struct-and-no-more BazPartOfBar,
}

When writing a non-trivial container, I found several user cases to be
extremely problematic. One was the above; a container held a "spine" or
"master" or "owned" or whatever-you-want-to-call-it data structure(s), plus
borrowed pointers that only live as long as the container and allow quick
access to specific parts of it.

Is this impossible in Rust (barring use of @ or unsafe pointers)?


On Sun, Sep 29, 2013 at 8:24 PM, Gábor Lehel <[email protected]> wrote:

> '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