Yeah, I was trying to come up with a design a while ago to allow
intrastructural borrowed pointers, and basically the effect this had was
that you could never move anything out of the datastructure since that
would leave dangling pointers. Which means you could grow the structure but
never shrink it, which is sort of not good.

Now my thought is about whether it would be possible to make a macro which
allows you to define a safely encapsulated smart node which ensures that
any intrastructural references meet certain invariants about where they
point within the structure, but I haven't developed the idea enough to say
whether you could make something truly general this way.


On Sun, Sep 29, 2013 at 7:28 PM, Steven Fackler <[email protected]>wrote:

> 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
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to