Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-10-26 Thread Oren Ben-Kiki
This is a good summary of the situation. There's one more twist to it
though; I not only want both ownership and aliasing, I also want
send-ability. That is, it should be possible to send the whole arena to
another task.

I think this rules out option 1 (though I don't know enough about lifetimes
to be sure). It leaves option 2 on the table, though.

The main problem with option 2 is that if one borrows a mutable pointer to
`root.poolOfSomeObjects[someIndex]` then the whole `root` is now considered
to be borrowed-as-mutable, disallowing borrowing a mutable pointer to
`root.poolOfOtherObjects[otherIndex]`. I'm tempted to say that the type
system should be smart enough to allow this, but I'm not 100% certain it
is actually safe to do so without some run-time support.

For now I am going with (3) which is using an UnsafePtr struct and scary
comments :-(


On Fri, Oct 25, 2013 at 7:05 PM, Niko Matsakis n...@alum.mit.edu wrote:

 On Mon, Sep 30, 2013 at 08:10:45PM +0300, Oren Ben-Kiki wrote:
  That's good! But there remains the fact that there's no way to say my
  lifetime is the same as the struct that contains me. If 'self
 specialness
  goes away, perhaps it can be re-introduced to mean that (or a different
  name can be given to it).

 So, I have had this thread on a must read list of e-mails for a while,
 but didn't get around to it until just now. Sorry about that.

 It is true that there is no way to have a lifetime that means as long
 as the current struct -- at least not in a type definition. The
 reason for this is that this is not a well-defined thing; structs can
 be moved, for example. The only place you can get a lifetime like that
 is in a method:

 fn foo'a('a mut self, ...)

 Here, 'a is the lifetime you are looking for (the current lifetime of
 the struct itself).

 We do have a way to express the notion of memory that moves with a
 struct and is freed when the struct is freed: ownership. That's what a
 `~` pointer is for. But of course the `~` pointer is designed for
 recursive ownership and transfers and thus prevents aliasing, which
 may not be what you need.

 Sometimes you want ownership and aliasability: basically you want to
 be able to create a subcomponent tied to a struct that will never
 itself be moved out of the struct into some other container. You can
 imagine doing this by having an arena that moves with the struct, and
 pointers that live as long as that arena. I had originally hoped to
 support this (that was indeed the origin of the 'self name) but it's
 quite complex to do so; that lifetime is a kind of existential
 lifetime and we don't really have a good way to capture it.

 In the meantime, you have two options:

 1. Parameterize the struct with a lifetime, and have it contain the
arena that way. This technique works when there is ultimately some
master stack frame that the struct will not outlive; this master
frame owns the arena, and the struct just borrows it. You can see
an example in this (yet to be landed) code. [1]

 2. Have the struct own a vector or other data structure, and replace
pointers with indices. This works best when the struct will be
moved around. You can see an example in this Graph data
structure. [2]

 While I know that neither technique feels perfect, they are quite
 workable, and I have used both with much rejoicing.



 Niko

 [1] https://gist.github.com/nikomatsakis/7157110
 [2]
 https://github.com/mozilla/rust/blob/master/src/librustc/middle/graph.rs

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
Huh, this is _exactly_ my use case. I have data structures which I grow but
never shrink, and I never move anything out of them. This idiom isn't that
uncommon when writing in functional style...

I incrementally build a complex structure that allows quick access to the
same pieces using different criteria (e.g., access a piece by a unique id,
or look it up by a path, or via a direct pointer held by a related piece,
etc.). All accesses are of (possibly mutable) borrowed pointers that live
as long as the whole thing exist. Then when done I can discard the whole
thing.

Sometimes I have a less-complex structure to which I attach a related
view structure. The view holds borrowed pointers to pieces of the
original immutable structure, allowing efficient access in new and
interesting ways. When done I can then discard the view and keep the
original.

So basically, I want something that gives me the freedoms granted to
'static, but only for as long as the main structure provably exists.
Something like 'shadow :-)

I found Rust doesn't like these idioms at all. I some cases, where I was
too tired, performance wasn't an issue, and there was no need to send the
whole thing between tasks, I just used @ pointers. Otherwise, I used RcMut,
though this incurs boilerplate access code and hurts performance for no
real reason. In critical cases I may end up using unsafe pointers...

Using a macro - hmm. Interesting and if possible, would be a great
solution. I'm not certain what such a macro would expand to, though. It
would need to be something that would express the concept of I live only
as long as my container structure _somehow_, and I thought we established
that can't be done...

Thanks,

Oren.

On Mon, Sep 30, 2013 at 4:26 AM, Steven Blenkinsop steven...@gmail.comwrote:

 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 
 sfack...@andrew.cmu.eduwrote:

 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 tku...@cmu.edu 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]
 }
 }


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Gábor Lehel
On Mon, Sep 30, 2013 at 8:31 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Huh, this is _exactly_ my use case. I have data structures which I grow
 but never shrink, and I never move anything out of them. This idiom isn't
 that uncommon when writing in functional style...

 I incrementally build a complex structure that allows quick access to the
 same pieces using different criteria (e.g., access a piece by a unique id,
 or look it up by a path, or via a direct pointer held by a related piece,
 etc.). All accesses are of (possibly mutable) borrowed pointers that live
 as long as the whole thing exist. Then when done I can discard the whole
 thing.


Just a thought, but when you write incrementally build a complex structure
... discard the whole thing, I think arena allocation. That /might/
solve your borrowed pointer woes by letting you pervasively use borrowed
pointers which all live at-most-as-long-as the arena (and hence the
structure) itself. The borrow checker in my head is not advanced enough to
let me really think it through though. And I don't think the compiler will
let you send anything if there are borrowed pointers involved. There's an
`arena` module[1] in libextra, but I've never tried it, and it uses `@`
pointers internally which also precludes sending.

(I wonder if there's any way to safely encode the idea that if all pointers
are internal to the arena (there's nothing pointing in or out), then
sending an ~arena should be safe, because its location in memory doesn't
change. Presumably you would also need to move-send a pointer to the
beginning of the structure inside of the arena alongside it. Maybe borrowed
pointers are not the best fit here, or maybe they are, I dunno.)

[1]: http://static.rust-lang.org/doc/master/extra/arena/struct.Arena.html




 Sometimes I have a less-complex structure to which I attach a related
 view structure. The view holds borrowed pointers to pieces of the
 original immutable structure, allowing efficient access in new and
 interesting ways. When done I can then discard the view and keep the
 original.

 So basically, I want something that gives me the freedoms granted to
 'static, but only for as long as the main structure provably exists.
 Something like 'shadow :-)

 I found Rust doesn't like these idioms at all. I some cases, where I was
 too tired, performance wasn't an issue, and there was no need to send the
 whole thing between tasks, I just used @ pointers. Otherwise, I used RcMut,
 though this incurs boilerplate access code and hurts performance for no
 real reason. In critical cases I may end up using unsafe pointers...

 Using a macro - hmm. Interesting and if possible, would be a great
 solution. I'm not certain what such a macro would expand to, though. It
 would need to be something that would express the concept of I live only
 as long as my container structure _somehow_, and I thought we established
 that can't be done...

 Thanks,

 Oren.

 On Mon, Sep 30, 2013 at 4:26 AM, Steven Blenkinsop steven...@gmail.comwrote:

 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 
 sfack...@andrew.cmu.eduwrote:

 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 tku...@cmu.edu 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]
 }
 }


 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev



[rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Steven Blenkinsop
On Monday, 30 September 2013, Oren Ben-Kiki wrote:

 Yes, it is very much like an arena... And yes, the idea is that all the
 pointers are contained in it, so the ~arena as a whole should be safe to
 send, but that contradicts using @ - maybe it could be re-written using
 Rc... hmmm. At any rate, thanks for the pointer - I wasn't aware of arenas
 before.

 Another hmmm... An arena sounds a lot like a weak version of a GC-ed
 heap... So here's a thought: What if @ pointers had a heap associated with
 them, just like  pointers have a lifetime? We have the task-global @ heap,
 and we have the static  lifetime... but we can explicitly manage 
 lifetimes - how about if we could explicitly create a new Gc-heap use it to
 happily muck about with @'my-heap pointers (which would be statically
 prevented from being mixed with @'other-heap pointers), and be able to send
 the whole heap between tasks, etc.? (Not that I necessarily suggest @'heap
 as a syntax, but you get the idea)

 Gc would still run in the context of one heap at a time... but this would
 remove the restriction of one task = one heap.


This would be neat, yes. In this case, accessing such a heap would be
conceptually identical to temporarily joining a task, except without the
overhead of having to schedule it, since it would have no independently
executing code. Figuring out how to hook it into the GC would be a neat
trick...

As for what a macro would expand to, I was thinking more that it would
expand to the containing structure and some smart references that use
lifetimes to ensure that the containing structure is pinned during their
existence and that they don't outlive it. You'd have to interact with it
using methods which make sure you can't break any of the invariants, such
as aliasing something and then trying to freeze it. To what extent you
could do this statically rather than dynamically, I'm not sure, but
lifetimes are a fairly powerful concept, so it's plausible one could work
something out. Doing it dynamically would basically mean using Cells
modified to have lifetimes as the smart references into the structure. It
would be nice to have a version of the smart references that ensured you
didn't externally alias something which is also externally mutable, though.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
I see what you mean about the macro - it would get quite complex though.

Regardless of macros, neat extensions with GC heaps and arenas and so on...

I still find it surprising that it is flat-out impossible to explicitly
name the default lifetime of a struct, and also that the natural name for
this lifetime ('self) is used for an entirely different purpose.

It would be nice if we could rename the existing 'self to something
(anything :-) else, and allow 'self to be used in struct field types and
elsewhere for the more natural (and currently unavailable) lifetime of the
current struct. Yes, this comes with some limitations, but it is useful
for some interesting cases and its lack of an explicit name seems arbitrary
(it is the default in many cases, after all).

At any rate, I now have a better grasp of what is going on, so I have a
better chance of writing code that actually works :-)

Thanks for the explanations!


On Mon, Sep 30, 2013 at 5:34 PM, Steven Blenkinsop steven...@gmail.comwrote:

 On Monday, 30 September 2013, Oren Ben-Kiki wrote:

 Yes, it is very much like an arena... And yes, the idea is that all the
 pointers are contained in it, so the ~arena as a whole should be safe to
 send, but that contradicts using @ - maybe it could be re-written using
 Rc... hmmm. At any rate, thanks for the pointer - I wasn't aware of arenas
 before.

 Another hmmm... An arena sounds a lot like a weak version of a GC-ed
 heap... So here's a thought: What if @ pointers had a heap associated with
 them, just like  pointers have a lifetime? We have the task-global @ heap,
 and we have the static  lifetime... but we can explicitly manage 
 lifetimes - how about if we could explicitly create a new Gc-heap use it to
 happily muck about with @'my-heap pointers (which would be statically
 prevented from being mixed with @'other-heap pointers), and be able to send
 the whole heap between tasks, etc.? (Not that I necessarily suggest @'heap
 as a syntax, but you get the idea)

 Gc would still run in the context of one heap at a time... but this would
 remove the restriction of one task = one heap.


 This would be neat, yes. In this case, accessing such a heap would be
 conceptually identical to temporarily joining a task, except without the
 overhead of having to schedule it, since it would have no independently
 executing code. Figuring out how to hook it into the GC would be a neat
 trick...

 As for what a macro would expand to, I was thinking more that it would
 expand to the containing structure and some smart references that use
 lifetimes to ensure that the containing structure is pinned during their
 existence and that they don't outlive it. You'd have to interact with it
 using methods which make sure you can't break any of the invariants, such
 as aliasing something and then trying to freeze it. To what extent you
 could do this statically rather than dynamically, I'm not sure, but
 lifetimes are a fairly powerful concept, so it's plausible one could work
 something out. Doing it dynamically would basically mean using Cells
 modified to have lifetimes as the smart references into the structure. It
 would be nice to have a version of the smart references that ensured you
 didn't externally alias something which is also externally mutable, though.

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Benjamin Striegel
I've only skimmed this conversation, but note that the specialness of the
'self lifetime will be going away in the future.


On Mon, Sep 30, 2013 at 10:48 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I see what you mean about the macro - it would get quite complex though.

 Regardless of macros, neat extensions with GC heaps and arenas and so on...

 I still find it surprising that it is flat-out impossible to explicitly
 name the default lifetime of a struct, and also that the natural name for
 this lifetime ('self) is used for an entirely different purpose.

 It would be nice if we could rename the existing 'self to something
 (anything :-) else, and allow 'self to be used in struct field types and
 elsewhere for the more natural (and currently unavailable) lifetime of the
 current struct. Yes, this comes with some limitations, but it is useful
 for some interesting cases and its lack of an explicit name seems arbitrary
 (it is the default in many cases, after all).

 At any rate, I now have a better grasp of what is going on, so I have a
 better chance of writing code that actually works :-)

 Thanks for the explanations!


 On Mon, Sep 30, 2013 at 5:34 PM, Steven Blenkinsop steven...@gmail.comwrote:

 On Monday, 30 September 2013, Oren Ben-Kiki wrote:

 Yes, it is very much like an arena... And yes, the idea is that all the
 pointers are contained in it, so the ~arena as a whole should be safe to
 send, but that contradicts using @ - maybe it could be re-written using
 Rc... hmmm. At any rate, thanks for the pointer - I wasn't aware of arenas
 before.

 Another hmmm... An arena sounds a lot like a weak version of a GC-ed
 heap... So here's a thought: What if @ pointers had a heap associated with
 them, just like  pointers have a lifetime? We have the task-global @ heap,
 and we have the static  lifetime... but we can explicitly manage 
 lifetimes - how about if we could explicitly create a new Gc-heap use it to
 happily muck about with @'my-heap pointers (which would be statically
 prevented from being mixed with @'other-heap pointers), and be able to send
 the whole heap between tasks, etc.? (Not that I necessarily suggest @'heap
 as a syntax, but you get the idea)

 Gc would still run in the context of one heap at a time... but this
 would remove the restriction of one task = one heap.


 This would be neat, yes. In this case, accessing such a heap would be
 conceptually identical to temporarily joining a task, except without the
 overhead of having to schedule it, since it would have no independently
 executing code. Figuring out how to hook it into the GC would be a neat
 trick...

 As for what a macro would expand to, I was thinking more that it would
 expand to the containing structure and some smart references that use
 lifetimes to ensure that the containing structure is pinned during their
 existence and that they don't outlive it. You'd have to interact with it
 using methods which make sure you can't break any of the invariants, such
 as aliasing something and then trying to freeze it. To what extent you
 could do this statically rather than dynamically, I'm not sure, but
 lifetimes are a fairly powerful concept, so it's plausible one could work
 something out. Doing it dynamically would basically mean using Cells
 modified to have lifetimes as the smart references into the structure. It
 would be nice to have a version of the smart references that ensured you
 didn't externally alias something which is also externally mutable, though.



 ___
 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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
That's good! But there remains the fact that there's no way to say my
lifetime is the same as the struct that contains me. If 'self specialness
goes away, perhaps it can be re-introduced to mean that (or a different
name can be given to it).


On Mon, Sep 30, 2013 at 7:01 PM, Benjamin Striegel
ben.strie...@gmail.comwrote:

 I've only skimmed this conversation, but note that the specialness of
 the 'self lifetime will be going away in the future.

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Vladimir Matveev
I think I should have put my code to gist to track changes easily.
Amending: https://gist.github.com/dpx-infinity/6751843

2013/9/29 Vladimir Matveev dpx.infin...@gmail.com:
 Yes, this is what I have observed too, see issue
 https://github.com/mozilla/rust/issues/9597. I didn't know that using
 extra parameter with lifetime will help though. It indeed works. But I
 think that polluting traits-interfaces with lifetime annotation is
 wrong. Why the trait should have lifetime annotation? It is
 implementation detail.

 I just managed to do what I wanted with some kind of hack. The
 following code compiles and works:

 // Some business-logic trait
 trait Walker {
 fn walk(self);  // Just self, without pointers
 }

 // ReaderContainer implementation remains the same

 // A struct which is intended to be an implementor of Walker trait
 // Note that it has lifetime parameter in order to work for any kind
 // of pointer to a Reader
 struct ReaderContainer'self {
 priv reader: 'self Reader,
 priv counter: int
 }

 // Some auxiliary structure for ReaderContainer
 // It may be anything but it should have a reference to ReaderContainer
 // We have to use lifetime parameter because this structure is 'attached'
 // to ReaderContainer, hence it must be of the same lifetime
 struct ReaderContainerIterator'self {
 priv container: 'self mut ReaderContainer'self
 }

 // Some made-up implementation of iterator protocol for our
 // auxiliary structure, it does not really matter
 impl'self Iteratoru8 for ReaderContainerIterator'self {
 fn next(mut self) - Optionu8 {
 if self.container.counter  10 {
 self.container.counter += 1;
 Some(self.container.reader.read_byte() as u8)
 } else {
 None
 }
 }
 }

 impl'self ReaderContainer'self {
 // A constructor for ReaderContainer, nothing special
 fn new'a(reader: 'a Reader) - ReaderContainer'a {
 ReaderContainer { reader: reader, counter: 0 }
 }

 // A method which returns our auxiliary structure, i.e. iterator
 // Note that self parameter has lifetime 'self, otherwise this naturally
 // does not compile
 fn iter('self mut self) - ReaderContainerIterator'self {
 ReaderContainerIterator { container: self }
 }
 }

 // And here are the changes

 // We implement Walker for a reference of the specific type!
 impl'self Walker for 'self mut ReaderContainer'self {
 // Here self automatically is 'self mut reference, so we can safely
 // use iter() method
 fn walk(self) {
 for b in self.iter() {
 println(fmt!(byte %?, b));
 }
 }
 }

 fn main() {
 use std::io;

 let r = io::stdin();
 let mut c = ReaderContainer::new(r);

 c.walk();  // No extra parameters
 }


 In short, I'm implementing `Walker` trait not for
 `ReaderContainer'self` but for `'self mut ReaderContainer'self`.

 This does not feel right, but I do not see immediate problems with
 this solution. Maybe someone who knows more about lifetimes could
 comment on this.

 2013/9/29 David Renshaw dwrens...@gmail.com:
 If I drop the unused parameter, I get an internal compiler error:
 'assertion failed: self.variance.is_some()'
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Gábor Lehel
'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.comwrote:

 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
 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Vladimir Matveev
As far as I understand, you're mostly right, except the structures bit.

Disregarding that it is not possible to use several lifetime
parameters yet, I see only one slight mistake: `s: MyStruct'a` does
not imply that `s` variable has any specific lifetime. If it is a
local variable, then it has 'lexical' lifetime; if it is a field in a
structure, it has lifetime of the structure instance.

 I guess what you meant is this:

s: 'a MyStruct'a

Here `s` pointer have lifetime 'a, as well as `s.r_int`.

BTW, you came up with very nice math-like analogy, it helped me
understand this thing even more. Thanks :)

2013/9/29 Gábor Lehel illiss...@gmail.com:
 '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 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
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 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 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Gábor Lehel
`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 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
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.orgwrote:

 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 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Steven Fackler
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 tku...@cmu.edu 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 o...@ben-kiki.org 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 illiss...@gmail.comwrote:


 `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki o...@ben-kiki.orgwrote:

 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.comwrote:

 '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 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Steven Blenkinsop
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 sfack...@andrew.cmu.eduwrote:

 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 tku...@cmu.edu 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 o...@ben-kiki.org 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 illiss...@gmail.comwrote:


 `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki o...@ben-kiki.orgwrote:

 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.comwrote:

 '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 

[rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-28 Thread Vladimir Matveev
Hi all,

The problem I'm writing about in this message follows from the one I
have described in my other message:
https://mail.mozilla.org/pipermail/rust-dev/2013-August/005281.html .
I believe I'm now able to formulate it more clearly.

Consider the following example code:

trait Walker {  // Some business-logic trait
fn walk(mut self);
}

// A struct which is intended to be an implementor of Walker trait
// Note that it has lifetime parameter in order to work for any kind
// of pointer to a Reader
struct ReaderContainer'self {
priv reader: 'self Reader,
priv counter: int
}

// Some auxiliary structure for ReaderContainer
// It may be anything but it should have a reference to ReaderContainer
// We have to use lifetime parameter because this structure is 'attached'
// to ReaderContainer, hence it must be of the same lifetime
struct ReaderContainerIterator'self {
priv container: 'self mut ReaderContainer'self
}

// Some made-up implementation of iterator protocol for our
// auxiliary structure, it does not really matter
impl'self Iteratoru8 for ReaderContainerIterator'self {
fn next(mut self) - Optionu8 {
if self.container.counter  10 {
self.container.counter += 1;
Some(self.container.reader.read_byte() as u8)
} else {
None
}
}
}

impl'self ReaderContainer'self {
// A constructor for ReaderContainer, nothing special
fn new'a(reader: 'a Reader) - ReaderContainer'a {
ReaderContainer { reader: reader, counter: 0 }
}

// A method which returns our auxiliary structure, i.e. iterator
// Note that self parameter has lifetime 'self, otherwise this naturally
// does not compile
fn iter('self mut self) - ReaderContainerIterator'self {
ReaderContainerIterator { container: self }
}
}

// Here is the problem: we cannot implement Walker trait!
impl'self Walker for ReaderContainer'self {
// See below for concrete errors description
fn walk(mut self) {  // 
for b in self.iter() {
println(fmt!(byte %?, b));
}
}
}

fn main() {
use std::io;

let r = io::stdin();
let mut c = ReaderContainer::new(r);

c.walk();
}


This program does not compile with the following error:

temp.rs:52:17: 52:30 error: cannot infer an appropriate lifetime due
to conflicting requirements
temp.rs:52 for b in self.iter() {
^
temp.rs:52:17: 52:22 note: first, the lifetime cannot outlive the
expression at 52:17...
temp.rs:52 for b in self.iter() {
^
temp.rs:52:17: 52:22 note: ...due to the following expression
temp.rs:52 for b in self.iter() {
^
temp.rs:52:17: 52:30 note: but, the lifetime must be valid for the
method call at 52:17...
temp.rs:52 for b in self.iter() {
^
temp.rs:52:17: 52:22 note: ...due to the following expression
temp.rs:52 for b in self.iter() {
^
error: aborting due to previous error

This is somewhat expected, because `self` in `walk()` method
implementation does not have 'self lifetime, so it is impossible to
call `iter()` method which needs concrete 'self lifetime. But I cannot
mark it with 'self lifetime either! If I do mark it with 'self:

fn walk('self mut self) {  // 
for b in self.iter() {
println(fmt!(byte %?, b));
}
}

Then the program fails to compile with another message:

temp.rs:51:4: 55:5 error: method `walk` has an incompatible type:
expected concrete lifetime, but found bound lifetime parameter 
temp.rs:51 fn walk('self mut self) {  // 
temp.rs:52 for b in self.iter() {
temp.rs:53 println(fmt!(byte %?, b));
temp.rs:54 }
temp.rs:55 }
temp.rs:51:29: 55:5 note: expected concrete lifetime is the lifetime
'self  as defined on the block at 51:29
temp.rs:51 fn walk('self mut self) {  // 
temp.rs:52 for b in self.iter() {
temp.rs:53 println(fmt!(byte %?, b));
temp.rs:54 }
temp.rs:55 }
error: aborting due to previous error

This is also expected: adding 'self lifetime violates `Walker` trait
signature, in which `walk()` method has plain `mut self` parameter.

So, this is kind of dead end. I think this problem may be formulated
in short as follows: how to implement generic traits for structures
which have lifetime parameters which are used for `self` parameter in
structure methods implementations?

How to do what I want to do? Is it possible at all?

Regards,
Vladimir.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-28 Thread David Renshaw
If I add an unused parameter of type Option'self () to the walk()
method, I can get your example to compile:
https://gist.github.com/dwrensha/29ed998566e2f9218c18

On Sat, Sep 28, 2013 at 4:42 PM, Vladimir Matveev
dpx.infin...@gmail.com wrote:
 Hi all,

 The problem I'm writing about in this message follows from the one I
 have described in my other message:
 https://mail.mozilla.org/pipermail/rust-dev/2013-August/005281.html .
 I believe I'm now able to formulate it more clearly.

 Consider the following example code:

 trait Walker {  // Some business-logic trait
 fn walk(mut self);
 }

 // A struct which is intended to be an implementor of Walker trait
 // Note that it has lifetime parameter in order to work for any kind
 // of pointer to a Reader
 struct ReaderContainer'self {
 priv reader: 'self Reader,
 priv counter: int
 }

 // Some auxiliary structure for ReaderContainer
 // It may be anything but it should have a reference to ReaderContainer
 // We have to use lifetime parameter because this structure is 'attached'
 // to ReaderContainer, hence it must be of the same lifetime
 struct ReaderContainerIterator'self {
 priv container: 'self mut ReaderContainer'self
 }

 // Some made-up implementation of iterator protocol for our
 // auxiliary structure, it does not really matter
 impl'self Iteratoru8 for ReaderContainerIterator'self {
 fn next(mut self) - Optionu8 {
 if self.container.counter  10 {
 self.container.counter += 1;
 Some(self.container.reader.read_byte() as u8)
 } else {
 None
 }
 }
 }

 impl'self ReaderContainer'self {
 // A constructor for ReaderContainer, nothing special
 fn new'a(reader: 'a Reader) - ReaderContainer'a {
 ReaderContainer { reader: reader, counter: 0 }
 }

 // A method which returns our auxiliary structure, i.e. iterator
 // Note that self parameter has lifetime 'self, otherwise this naturally
 // does not compile
 fn iter('self mut self) - ReaderContainerIterator'self {
 ReaderContainerIterator { container: self }
 }
 }

 // Here is the problem: we cannot implement Walker trait!
 impl'self Walker for ReaderContainer'self {
 // See below for concrete errors description
 fn walk(mut self) {  // 
 for b in self.iter() {
 println(fmt!(byte %?, b));
 }
 }
 }

 fn main() {
 use std::io;

 let r = io::stdin();
 let mut c = ReaderContainer::new(r);

 c.walk();
 }


 This program does not compile with the following error:

 temp.rs:52:17: 52:30 error: cannot infer an appropriate lifetime due
 to conflicting requirements
 temp.rs:52 for b in self.iter() {
 ^
 temp.rs:52:17: 52:22 note: first, the lifetime cannot outlive the
 expression at 52:17...
 temp.rs:52 for b in self.iter() {
 ^
 temp.rs:52:17: 52:22 note: ...due to the following expression
 temp.rs:52 for b in self.iter() {
 ^
 temp.rs:52:17: 52:30 note: but, the lifetime must be valid for the
 method call at 52:17...
 temp.rs:52 for b in self.iter() {
 ^
 temp.rs:52:17: 52:22 note: ...due to the following expression
 temp.rs:52 for b in self.iter() {
 ^
 error: aborting due to previous error

 This is somewhat expected, because `self` in `walk()` method
 implementation does not have 'self lifetime, so it is impossible to
 call `iter()` method which needs concrete 'self lifetime. But I cannot
 mark it with 'self lifetime either! If I do mark it with 'self:

 fn walk('self mut self) {  // 
 for b in self.iter() {
 println(fmt!(byte %?, b));
 }
 }

 Then the program fails to compile with another message:

 temp.rs:51:4: 55:5 error: method `walk` has an incompatible type:
 expected concrete lifetime, but found bound lifetime parameter 
 temp.rs:51 fn walk('self mut self) {  // 
 temp.rs:52 for b in self.iter() {
 temp.rs:53 println(fmt!(byte %?, b));
 temp.rs:54 }
 temp.rs:55 }
 temp.rs:51:29: 55:5 note: expected concrete lifetime is the lifetime
 'self  as defined on the block at 51:29
 temp.rs:51 fn walk('self mut self) {  // 
 temp.rs:52 for b in self.iter() {
 temp.rs:53 println(fmt!(byte %?, b));
 temp.rs:54 }
 temp.rs:55 }
 error: aborting due to previous error

 This is also expected: adding 'self lifetime violates `Walker` trait
 signature, in which `walk()` method has plain `mut self` parameter.

 So, this is kind of dead end. I think this problem may be formulated
 in short as follows: how to implement generic traits for structures
 which have lifetime parameters which are used for `self` parameter in
 structure methods implementations?

 How to do what I want to do? Is it possible at all?

 Regards,
 Vladimir.
 

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-28 Thread David Renshaw
If I drop the unused parameter, I get an internal compiler error:
'assertion failed: self.variance.is_some()'
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev