Oooh fun you’ve hit your first rustc bug! Great!



https://github.com/rust-lang/rust/issues/17178





Niko is already working on this, so a fix is coming soon. Both of those 
constructions should have failed. The correct way to fix this is:




```

let weights = [ 3,5,7 ];

let b = InBag(Bag { price: 10, weights: weights.as_slice() });

```

On Fri, Oct 17, 2014 at 12:30 PM, David Henningsson <di...@ubuntu.com>
wrote:

> First, big thanks to both of you, Ben and Clark, for helping out. :-)
> Thanks for the hint on the lifetime syntax - it's a bit hard to grasp, 
> sometimes it's "Foo<'a>", sometimes it's "& 'a [Foo]", and I've seen 
> examples with "Foo+'a" too. But maybe this all makes sense when I'm more 
> used to the language.
> As for how long the pointed-to data is alive for, I think it makes sense 
> to default to "the same lifetime as parent struct or enum", if the 
> lifetime is not explicitly specified.
> Btw, for some reason this does not work:
> let s = InBag(Bag { price: 10, weights: &[3, 5, 7] }); /* fails with 
> "borrowed value does not live long enough" and "consider using a `let` 
> binding to increase its lifetime" */
> But the below does, and can be used as a workaround:
>     let b = Bag { price: 10, weights: &[3, 5, 7] };
>     let s = InBag(b);
> I'm sure there's an explanation to why, but if it can be fixed so that 
> the compiler interprets the first as being equivalent to the second it 
> would be nice.
> On 2014-10-17 21:01, Ben Foppa wrote:
>> Your struct has a fixed size - a reference is a pointer. Which is why 
>> it requires a lifetime - how long is the pointed-to data alive for? 
>> And so you need to tell it - in your enum example, you need to say 
>> Bag<'a> (for some defined 'a). For example, Bag<'static> means the 
>> pointed-to data lives as long as the program.
>>
>> On Fri, Oct 17, 2014 at 11:50 AM, David Henningsson <di...@ubuntu.com 
>> <mailto:di...@ubuntu.com>> wrote:
>>
>>     Thanks for the answer. Deref is a new one for me, looks
>>     interesting by means of abstraction.
>>
>>     I'm also coming from the C camp but I'm not sure how to write the
>>     code that I want in rust. Yet. :-)
>>
>>     E g, here's one, somewhat related, C example that I'm not sure how
>>     to do in Rust:
>>
>>     struct bag {
>>        int price;
>>        int nitems;
>>        int []items;
>>     };
>>
>>     struct cart { /* ... */ };
>>
>>     struct shopping {
>>        int kind; /* 0 means bag, 1 means cart */
>>        union {
>>           struct bag bag;
>>           struct cart cart;
>>        }
>>     }
>>
>>     struct shopping* make_shopping_bag(int price, int nitems, int *items)
>>     {
>>         struct shopping* result =
>>     malloc(sizeof(shopping)+nitems*sizeof(int));
>>         result.kind = 0;
>>         result.bag.price = price;
>>         result.bag.nitems = nitems;
>>         memcpy(result.bag.items, nitems*sizeof(int));
>>     }
>>
>>
>>     So, the bag struct would probably look like this in Rust:
>>
>>     struct Bag <'a> {
>>       price: int,
>>       weights: & 'a [int],
>>     }
>>
>>      1) It feels like "weights: [int]" would be more like the way I
>>     want it, and the declaration compiles, but i can't initialize the
>>     struct or have it as a local variable because its size is now
>>     unkown. Even though a static initialization like "let b = Bag {
>>     price: 10, weights: [3,5,7] }" would be trivial to calculate the
>>     total size of, the compiler seems not to be able to do this.
>>
>>      2) I'm not sure why this lifetime has to be explicit, should
>>     default to "same lifetime as parent struct" IMO.
>>
>>      3) And when I try to do like:
>>
>>     enum Shopping {
>>       InBag(Bag),
>>       InCart( /* ... */ ),
>>     }
>>
>>     I get an error: "error: wrong number of lifetime parameters:
>>     expected 1, found 0". I've tried both "InBag('a Bag)" and
>>     "InBag(Bag + 'a)" but that ends up with other errors instead...so
>>     no idea on what to do about that?
>>
>>
>>     On 2014-10-17 18:37, Clark Gaebel wrote:
>>>     Rust is not a replacement for java, it’s a replacement for C and C++.
>>>
>>>     To solve little “puzzles” like this, i tend to ask myself “how
>>>     would I do this in C”, and then write that code in rust. Building
>>>     inheritance trees is generally the wrong way of approaching
>>>     problems. In cases where it does apply, you can still do it, but
>>>     be gentle. Try not to lean on them as your primary means of
>>>     abstraction.
>>>
>>>     Anyhow, on to your actual problem.
>>>
>>>     Something which might be worth trying is implementing
>>>     `Deref<Circle>` and `DerefMut<Circle>` for your pancake, then
>>>     having a `DList<Box<Deref<Circle>>>` (or just use a normal &, if
>>>     you want that).
>>>
>>>     Then you can call all your circle traits after a quick call to
>>>     `.deref()`, AND your `DList` will free everything properly.
>>>
>>>     But again, there’s probably a simpler solution that doesn’t
>>>     involve “inheritance” that you should consider. Maybe a DList of
>>>     enums? Maybe just a Vec<uint> in this case? Think about how you’d
>>>     do it in C.
>>>
>>>     Regards,
>>>       - Clark
>>>
>>>
>>>
>>>     On Fri, Oct 17, 2014 at 4:27 AM, David Henningsson
>>>     <di...@ubuntu.com <mailto:di...@ubuntu.com>> wrote:
>>>
>>>         Hmm, right. The as_* could probably useful to write a macro for.
>>>
>>>         Coming from the C/Java side of things I have to figure out
>>>         how this
>>>         works in a bigger context, e g a DList or other structure
>>>         owning objects
>>>         implementing HasArea. This seems to compile, e g:
>>>
>>>         impl Pancake {
>>>         fn as_box_circle(&self) -> Box<Circle> { box self.circle }
>>>         }
>>>
>>>         fn make_pancake(dl: &mut DList<Box<HasArea>>) {
>>>         let p = Pancake { circle: Circle { x: 0f64, y: 0f64, radius:
>>>         1f64
>>>         }, is_tasty: true };
>>>         dl.push(p.as_box_circle());
>>>         }
>>>
>>>         But I'd assume that make_pancake would now make a copy of the
>>>         pancake's
>>>         circle, rather than taking ownership of the entire pancake,
>>>         right? The
>>>         pancake then gets dropped at function return.
>>>
>>>         In this simple example perhaps this does not make that much of a
>>>         difference though, but if you imagine a C struct like:
>>>
>>>         struct list {
>>>         list *next;
>>>         circle *data;
>>>         }
>>>
>>>         You can now put a pointer to a pancake as data, use it as a
>>>         circle, and
>>>         when you finally free the list and the data that goes with
>>>         it, the
>>>         entire pancake will be freed. This you cannot do in rust...or
>>>         can you?
>>>
>>>
>>>         On 2014-10-17 07:59, Clark Gaebel wrote:
>>>         > impl Pancake {
>>>         > fn as_circle(&self) -> &Circle { &self.circle }
>>>         > fn as_mut_circle(&mut self) -> &mut Circle { &mut
>>>         self.circle }
>>>         > }
>>>         >
>>>         > The compiler will optimize trivial functions, except
>>>         cross-crate. In
>>>         > those cases, use an #[inline] annotation.
>>>         >
>>>         >
>>>         >
>>>         > On Thu, Oct 16, 2014 at 10:57 PM, David Henningsson
>>>         <di...@ubuntu.com <mailto:di...@ubuntu.com>
>>>         > <mailto:di...@ubuntu.com> <mailto:di...@ubuntu.com>> wrote:
>>>         >
>>>         > This is probably a previously asked question, but I
>>>         couldn't find
>>>         > it on
>>>         > Google, so...
>>>         >
>>>         > Let's extend the Circle example from the guide a little:
>>>         >
>>>         > struct Circle {
>>>         > x:f64,
>>>         > y:f64,
>>>         > radius:f64,
>>>         > }
>>>         >
>>>         > trait HasArea {
>>>         > fn area(&self)-> f64;
>>>         > }
>>>         >
>>>         > impl HasArea for Circle {
>>>         > fn area(&self)-> f64 {
>>>         > std::f64::consts::PI * (self.radius * self.radius)
>>>         > }
>>>         > }
>>>         >
>>>         > struct Pancake {
>>>         > circle: Circle,
>>>         > is_tasty: bool,
>>>         > }
>>>         >
>>>         >
>>>         > ...now, what is the easiest way I can implement HasArea for
>>>         > Pancake? I
>>>         > could do this:
>>>         >
>>>         > impl HasArea for Pancake {
>>>         > fn area(&self) -> f64 { self.circle.area() }
>>>         > }
>>>         >
>>>         > ...but that means a lot of boiler-plate code, especially if
>>>         > HasArea has
>>>         > many methods. Hopefully rust will just inline/optimise the
>>>         > redirection
>>>         > away in most cases to avoid the runtime cost, but is there a
>>>         > smarter or
>>>         > more idiomatic way of doing this?
>>>         >
>>>         > // David
>>>         >
>>>         > _______________________________________________
>>>         > Rust-dev mailing list
>>>         > Rust-dev@mozilla.org <mailto:Rust-dev@mozilla.org>
>>>         > https://mail.mozilla.org/listinfo/rust-dev
>>>         >
>>>         >
>>>
>>>
>>
>>
>>     _______________________________________________
>>     Rust-dev mailing list
>>     Rust-dev@mozilla.org <mailto: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

Reply via email to