That's... surprising. Even ignoring the fact the name "self" means exactly the opposite (déjà vu from "const" here)...
I don't suppose there's a chance that something like what I expected 'self to be like would be supported at some point? Its lack rules out a lot of reasonable, safe, useful code. On Mon, Sep 30, 2013 at 12:13 AM, Gábor Lehel <illiss...@gmail.com> wrote: > > `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki <o...@ben-kiki.org> wrote: > >> 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, >> } >> > > Per my understanding, this is correct. Because there is a constraint on > the lifetime of a part of `Foo`, there must a constraint on the lifetime of > `Foo`. It has to propagate outwards to make sure the lifetime of the whole > structure is properly constrained. You basically want to "propagate > inwards". I don't think that's possible, but maybe someone will correct me. > > >> >> 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)? >> > > This sounds similar to the case of a doubly linked list (with forward > pointers being the "spine" and backwards the "quick access"), which is not > possible as an 'owned' structure as far as I know without unsafe pointers. > > >> >> >> On Sun, Sep 29, 2013 at 8:24 PM, Gábor Lehel <illiss...@gmail.com> 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 <o...@ben-kiki.org>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 <dwrens...@gmail.com>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 >>>>> Rust-dev@mozilla.org >>>>> https://mail.mozilla.org/listinfo/rust-dev >>>>> >>>> >>>> >>>> _______________________________________________ >>>> Rust-dev mailing list >>>> Rust-dev@mozilla.org >>>> https://mail.mozilla.org/listinfo/rust-dev >>>> >>>> >>> >>> >>> -- >>> Your ship was destroyed in a monadic eruption. >>> >> >> > > > -- > Your ship was destroyed in a monadic eruption. >
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev