Foo can't really be used safely. Say that we have

struct Bar {
    baz: BazPartOfBar
}

struct Foo {
    bar: Bar,
    baz: &'magic BazPartOfBar
}

And let's say we add a `self` syntax to allow field initializers to refer
to other fields:

let foo = Foo {
    bar: Bar {
        baz: BazPartOfBar
    },
    baz: &self.bar.baz
};

We can't really do much with Foo. If we move it, foo.baz is no longer a
valid reference, so that can't happen. We could modify foo.bar in this
case, but not if Bar were defined as

struct Bar {
    baz: ~BazPartOfBar
}

since foo.baz would point to deallocated memory if we replace self.bar or
self.bar.baz.

Steven Fackler


On Sun, Sep 29, 2013 at 3:15 PM, Tim Kuehn <[email protected]> wrote:

> Could you use struct methods for "quick access"? Or is there a reason this
> wouldn't fit your use case? Sorry, I haven't followed the whole thread
> closely.
>
> struct Owner {
>     owned: ~[int],
> }
>
> impl Owner {
>     fn quick_access<'a>(&'a mut self) -> &'a mut int {
>         &mut self.owned[0]
>     }
> }
>
>
> On Sun, Sep 29, 2013 at 5:32 PM, Oren Ben-Kiki <[email protected]> wrote:
>
>> 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 <[email protected]>wrote:
>>
>>>
>>> `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki <[email protected]>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 <[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.
>>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> 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
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to