These are chat archives for rust-lang/rust

2nd
Mar 2019
niveau0
@niveau0
Mar 02 11:12

sometimes I'm still confused with type magic, can someone explain why this does not work:

               let lines = if msg.0.ends_with(".gz") {
                    BufReader::new(GzDecoder::new(f)).lines()
                } else {
                    BufReader::new(f).lines()
                };

but this is allowed:

               let lines: Box<Iterator<Item = std::io::Result<String>>> = if msg.0.ends_with(".gz")
                {
                    Box::new(BufReader::new(GzDecoder::new(f)).lines())
                } else {
                    Box::new(BufReader::new(f).lines())
                };

and maybe, is there still a way without boxing?

Zakarum
@omni-viral
Mar 02 11:37
@niveau0 last expressions on if-else should result in the same type
In first snipped it is obviously not the case
The second one wraps expressions into Box. It doesn't make expression to have the same type, but there is a trick.
if-else result is assigned to Box<Iterator<Item = ...>>
Which in 2018 we write as Box<dyn Iterator<Item = ...>>
Now both boxes in if and else arms can be coerced into Box<dyn Iterator<Item = ...>>
Why? Because types inside boxes implement the trait Iterator<Item ...>
And since boxed types are coerced to the same type we end up with if and else having expressions with the same type and compiler is happy
The other way around to do what you want without boxing is using enums
Zakarum
@omni-viral
Mar 02 11:43
Simply create an enum that can hold any of desired types and implement Iterator<Item = ...> trait for that enum type
Now you can wrap values into enum and voila
You still get dispatch, but enum dispatch tend to be much cheaper than dynamic trait dispatch and can be optimized
Also you don't heap allocate
Typically you need dyn trait only if set of types in not predefiend
For instance when user can provide you with his/her implementations
and generics can't be used
niveau0
@niveau0
Mar 02 11:48
@omni-viral ah nice, thanks for explanation, I try with enum wrapper then
tsoernes
@tsoernes
Mar 02 18:02
does collecting an interator into a vec allocate a vec with with_capacity?
or does it create a default sized vec whatever size that is then keeps growing it
Tim Robinson
@1tgr
Mar 02 18:07
It appears to use size_hint and with_capacity https://doc.rust-lang.org/stable/src/alloc/vec.rs.html#1807
David McGillicuddy
@djmcgill
Mar 02 19:57

I'm looking for a ring buffer to use in a no_std environment. I.e. I want writing to the buffer when it's full to overwrite the oldest element. The library heapless had a ring buffer type, that got renamed to Queue.
This method: https://japaric.github.io/heapless/heapless/spsc/struct.Queue.html#method.enqueue_unchecked
states:

If the queue is full this operation will leak a value (T's destructor won't run on the value that got overwritten by item), and will allow the dequeue operation to create a copy of item, which could result in T's destructor running on item twice.

Does that mean it will leak memory, or just not run the destructor? If my type is just usize, is that bad behaviour or not?

Alternatively, can somebody recommend a different type to pass data between interrupts and the main thread? I have the interrupt reading byte-by-byte into a fixed size array, and I'd like the main to see only the latest complete array.