Shouldn't R: AsRef<[T]> should work for T=u64? - rust

On the following:
pub fn a<
T: Copy,
R: AsRef<[T]>
>(
a_fn: &dyn Fn(&[R], &mut [u64]),
)
{
let mut result = vec![0, 3];
b(&[1,2,3], result.as_mut_slice());
}
fn b<T: Copy, R: AsRef<[T]>>(_: &[R], _: &mut [u64]) {
unimplemented!();
}
fn c() {
a::<u64, &[u64]>(&b);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=43d054772b15fa575cc75e87b4eb34d9
I'm trying to be generic on the type R, but eventually use a slice of u64. However, it looks like that [integer] does not implement AsRef<[T]>.
Error:
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `{integer}: AsRef<[_]>` is not satisfied
--> src/lib.rs:9:5
|
9 | b(&[1,2,3], result.as_mut_slice());
| ^ the trait `AsRef<[_]>` is not implemented for `{integer}`
|
= help: the following implementations were found:
<&T as AsRef<U>>
<&mut T as AsRef<U>>
<Arc<T> as AsRef<T>>
<Box<T, A> as AsRef<T>>
and 38 others
note: required by a bound in `b`
--> src/lib.rs:13:18
|
13 | fn b<T: Copy, R: AsRef<[T]>>(_: &[R], _: &mut [u64]) {
| ^^^^^^^^^^ required by this bound in `b`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

Change b to take R or &R rather than &[R]. &[R] == &[AsRef<[T]>] has nested slices which I take it is not your intention.
fn main() {
let mut result = vec![0, 3];
b(&[1,2,3], result.as_mut_slice());
}
fn b<T: Copy, R: AsRef<[T]>>(_: R, _: &mut [u64]) {
unimplemented!();
}
Playground

Related

Using reference lifetimes correctly in iterator

I am trying to make an iterator out of some struct, s1, that has references within it with some lifetimes, say 'a and 'b. The iterator elements are new instances of the same struct type holding the same references. When I try to do this, the iterator elements appear to become subject to the lifetime of s1 instead of just 'a and 'b.
An example for clarity:
#[derive(Debug)]
pub struct MyStruct<'a, 'b> {
num: i32,
ref1: &'a i32,
ref2: &'b i32,
}
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct> {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct{ num: 0, ref1: &i1, ref2: &i2 };
let s_next: Vec<_> = s1.with_next_nums(3).collect();
drop(s1); // commenting this line the program compiles
println!("{:?}", s_next);
}
The error I get is:
error[E0505]: cannot move out of `s1` because it is borrowed
--> src/main.rs:19:10
|
18 | let s_next: Vec<_> = s1.with_next_nums(3).collect();
| -------------------- borrow of `s1` occurs here
19 | drop(s1); // commenting this line the program compiles
| ^^ move out of `s1` occurs here
20 | println!("{:?}", s_next);
| ------ borrow later used here
For more information about this error, try `rustc --explain E0505`.
error: could not compile `playground` due to previous error
So, because I am dropping s1, Rust assumes the elements of s_next will become invalid, even though s_next only holds references to i1 and i2.
I suppose it is a matter of lifetime annotation, but I don't know how to fix it. If I were just producing a single struct out of s1, then I could annotate the return type like MyStruct<'a, 'b> and it would work, but just using impl Iterator<Item=MyStruct<'a, 'b>> as a return type does not solve it.
The problem with your version is that because of the lifetime elision rules, since you didn't specify the lifetimes for 'a and 'b in the returned MyStruct, the compiler assumes they have the same lifetime as self. So, this as if you wrote:
pub fn with_next_nums<'c>(&'c self, n: i32) -> impl Iterator<Item = MyStruct<'c, 'c>>
To fix that you need to explicitly declare the lifetimes as 'a and 'b:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>>
Now there will be another error in the declaration of with_next_nums(), because it does borrow from self as the closure captures it. You can fix that by adding '_, as the compiler suggests, but then your iterator will borrow from self, so your code (that collects them into a Vec) will work, but similar code that does not collect() immediately will not:
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct {
num: 0,
ref1: &i1,
ref2: &i2,
};
// The iterator is still alive when we drop `s1`, but it borrows from it.
let s_next = s1.with_next_nums(3);
drop(s1);
let s_next: Vec<_> = s_next.collect();
println!("{:?}", s_next);
}
A better fix is to change the closure so it will only borrow the fields it needs and not self. You can do it like that:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>> {
let MyStruct { num, ref1, ref2 } = *self;
(1..=n).map(move |i| MyStruct {
num: num + i,
ref1,
ref2,
})
}
The problem is that in this case you need to specify the lifetime of both the iterator elements and the iterator itself. If you just specify the lifetimes of the iterator elements (with impl Iterator<Item=MyStruct<'a, 'b>>), the compiler assumes you will deal with lifetimes by hand and will give up trying to automatically assign a lifetime to the iterator. However, it does need to have the lifetime of the struct, because it depends on it, so it will fail to compile. The compiler error will actually give you the fix in this case:
error[E0700]: hidden type for `impl Iterator<Item = MyStruct<'a, 'b>>` captures lifetime that does not appear in bounds
--> src/main.rs:10:9
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> {
| ----- hidden type `Map<RangeInclusive<i32>, [closure#src/main.rs:10:21: 10:24]>` captures the anonymous lifetime defined here
10 | (1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl Iterator<Item = MyStruct<'a, 'b>>` captures `'_`, you can add an explicit `'_` lifetime bound
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
| ++++
For more information about this error, try `rustc --explain E0700`.
error: could not compile `playground` due to previous error
So, you just need to also add that + '_ to the return type to solve the issue:
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}

Cannot call method because of unsatisfied trait bounds

I'm trying to implement parts of the minecraft protocol (https://wiki.vg/).
I've successfully implemented a decoder to decode packets. But I'm stuck with the encoding part. The thing is that the minecraft protocol uses "minecraft varints" (https://wiki.vg/Protocol#VarInt_and_VarLong) and I want to have methods to write data as varints.
So my goal is to have a trait named Encoder with these methods:
fn write_var_int(&mut self, value: i32) -> Result<(), error::EncodeError>;
fn write_var_long(&mut self, value: i64) -> Result<(), error::EncodeError>;
fn write_string(&mut self, value: &str) -> Result<(), error::EncodeError>;
At the moment, I've only written the code for the first method:
fn write_var_int(&mut self, mut value: i32) -> Result<(), error::EncodeError> {
loop {
let mut byte = (value & 0b01111111) as u8;
if byte == 0 {
self.write_u8(byte).unwrap();
break;
}
self.write_u8(byte | 0b10000000).unwrap();
value = value >> 7;
}
Ok(())
}
In main.rs I import the module Encoder and I try to use it on a cursor :
let test = [0; 17];
let mut wrt = Cursor::new(test);
wrt.write_var_int(packet.id);
But I get these compilation errors:
error[E0599]: the method `write_var_int` exists for struct `std::io::Cursor<[{integer}; 17]>`, but its trait bounds were not satisfied
--> src/main.rs:57:37
|
57 | ... wrt.write_var_int(packet.id);
| ^^^^^^^^^^^^^ method cannot be called on `std::io::Cursor<[{integer}; 17]>` due to unsatisfied trait bounds
|
::: /home/clement/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/cursor.rs:75:1
|
75 | pub struct Cursor<T> {
| --------------------
| |
| doesn't satisfy `std::io::Cursor<[{integer}; 17]>: Encoder`
| doesn't satisfy `std::io::Cursor<[{integer}; 17]>: std::io::Write`
|
note: the following trait bounds were not satisfied because of the requirements of the implementation of `Encoder` for `_`:
`std::io::Cursor<[{integer}; 17]>: std::io::Write`
--> src/protocol/encoder.rs:12:16
|
12 | impl<W: Write> Encoder for W {
| ^^^^^^^ ^
warning: unused import: `protocol::encoder::Encoder`
--> src/main.rs:11:5
|
11 | use protocol::encoder::Encoder;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0599`.
warning: `eupim` (bin "eupim") generated 2 warnings
error: could not compile `eupim` due to previous error; 2 warnings emitted
I don't understand why the import of the Encoder module is marked as unused, and how to fix these errors.
I'll be pleased to have hints on how to fix this.
Thanks!
I tried to turn the code in your question into a minumal reproducible example:
use std::io::{Cursor, Write};
use std::slice;
mod error {
#[derive(Debug)]
pub enum EncodeError { }
}
trait Encoder {
fn write_u8(&mut self, value: u8) -> Result<(), error::EncodeError>;
fn write_var_int(&mut self, value: i32) -> Result<(), error::EncodeError>;
}
impl<W: Write> Encoder for W {
fn write_u8(&mut self, value: u8) -> Result<(), error::EncodeError> {
self.write(slice::from_ref(&value)).unwrap();
Ok(())
}
fn write_var_int(&mut self, mut value: i32) -> Result<(), error::EncodeError> {
loop {
let mut byte = (value & 0b01111111) as u8;
if byte == 0 {
self.write_u8(byte).unwrap();
break;
}
self.write_u8(byte | 0b10000000).unwrap();
value = value >> 7;
}
Ok(())
}
}
fn main() {
let test = [0; 17];
let mut wrt = Cursor::new(test);
wrt.write_var_int(3);
}
This produces the error:
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `write_var_int` exists for struct `std::io::Cursor<[{integer}; 17]>`, but its trait bounds were not satisfied
--> src/main.rs:39:9
|
39 | wrt.write_var_int(3);
| ^^^^^^^^^^^^^ method cannot be called on `std::io::Cursor<[{integer}; 17]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied because of the requirements of the implementation of `Encoder` for `_`:
`std::io::Cursor<[{integer}; 17]>: std::io::Write`
--> src/main.rs:14:16
|
14 | impl<W: Write> Encoder for W {
| ^^^^^^^ ^
For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error
The problem here is that we've got a Cursor<[{integer}; 17]>, but Write is only implemented for a Cursor<&mut [u8]>, where &mut [u8] is a mutable reference to a u8 slice.
This makes sense if you think about it: Cursor wraps an in-memory buffer, but there's no need for it to take ownership of it.
So let's make sure we're passing a mutable slice to our Cursor:
fn main() {
let mut test = [0u8; 17];
let mut wrt = Cursor::new(&mut test[..]);
wrt.write_var_int(3);
}
This compiles as expected.

How can I clone a Vec<Box<dyn Trait>>?

I want to implement a function that takes an immutable &Vec reference, makes a copy, sorts the values and prints them.
This is the main code.
trait Foo {
fn value(&self) -> i32;
}
struct Bar {
x: i32,
}
impl Foo for Bar {
fn value(&self) -> i32 {
self.x
}
}
fn main() {
let mut a: Vec<Box<dyn Foo>> = Vec::new();
a.push(Box::new(Bar { x: 3 }));
a.push(Box::new(Bar { x: 5 }));
a.push(Box::new(Bar { x: 4 }));
let b = &a;
sort_and_print(&b);
}
The only way I was able to make it work was this
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = Vec::new();
for val in v {
v_copy.push(val);
}
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
However I want to understand what's happening here and also to make the code shorter.
Question 1
If I try to change let mut v_copy = Vec::new(); to let mut v_copy: Vec<Box<dyn Foo>> = Vec::new(); however that results in various errors that I don't know how to fix.
How do I make this version work and why is it different than the first version?
Attempt 2
Something closer to what I'm looking for is something like this.
let mut v_copy = v.clone(); but this doesn't work. Can this version be fixed?
First, let's annotate the types:
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<&Box<dyn Foo>> = Vec::new();
for val /* : &Box<dyn Foo> */ in v {
v_copy.push(val);
}
v_copy.sort_by_key(|o: &&Box<dyn Foo>| <dyn Foo>::value(&***o));
for val /* : &Box<dyn Foo> */ in v_copy {
println!("{}", <dyn Foo>::value(&**val));
}
}
Iterating over &Vec<T> produces an iterator over &T (the same as the .iter() method).
Now we can see we can convert it into iterator, by either calling .into_iter() on v and then .collect() (which is what the for loop does), or replace into_iter() with iter() (which is more idiomatic since we're iterating over references):
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<&Box<dyn Foo>> = v.iter().collect(); // You can omit the `&Box<dyn Foo>` and replace it with `_`, I put it here for clarity.
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
However, we still only have a copy of the reference (&Box<dyn Foo>). Why can't we just clone the vector?
If we try...
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
...the compiler yell at us:
warning: variable does not need to be mutable
--> src/main.rs:45:9
|
45 | let mut v_copy = v.clone();
| ----^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow `*v_copy` as mutable, as it is behind a `&` reference
--> src/main.rs:46:5
|
45 | let mut v_copy = v.clone();
| ---------- help: consider changing this to be a mutable reference: `&mut Vec<Box<dyn Foo>>`
46 | v_copy.sort_by_key(|o| o.value());
| ^^^^^^ `v_copy` is a `&` reference, so the data it refers to cannot be borrowed as mutable
WHAT???????????
Well, let's try to specify the type. It can make the compiler smarter.
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<Box<dyn Foo>> = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Nope.
error[E0308]: mismatched types
--> src/main.rs:45:41
|
45 | let mut v_copy: Vec<Box<dyn Foo>> = v.clone();
| ----------------- ^^^^^^^^^
| | |
| | expected struct `Vec`, found reference
| | help: try using a conversion method: `v.to_vec()`
| expected due to this
|
= note: expected struct `Vec<Box<dyn Foo>>`
found reference `&Vec<Box<dyn Foo>>`
Well, let's use the compiler's suggestion:
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<Box<dyn Foo>> = v.to_vec();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Grrr!!
error[E0277]: the trait bound `dyn Foo: Clone` is not satisfied
--> src/main.rs:45:43
|
45 | let mut v_copy: Vec<Box<dyn Foo>> = v.to_vec();
| ^^^^^^ the trait `Clone` is not implemented for `dyn Foo`
|
= note: required because of the requirements on the impl of `Clone` for `Box<dyn Foo>`
At least we now have some clues.
What happened here?
Well, like the compiler said, dyn Foo does not implement the Clone trait. Which means that neither does Box<dyn Foo>, and so is Vec<Box<dyn Foo>>.
However, &Vec<Box<dyn Foo>> actually does impl Clone. This is because you can have as many shared references as you want - shared (non-mutable) references are Copy, and every Copy is also Clone. Try it:
fn main() {
let i: i32 = 123;
let r0: &i32 = &i;
let r1: &i32 = <&i32 as Clone>::clone(&r0);
}
So, when we write v.clone(), the compiler asks "is there a method named clone() that takes self of type &Vec<Box<dyn Foo>> (v)?" it first looks for such method on the Clone impl for Vec<Box<dyn Foo>> (because the Clone::clone() takes &self, so for Vec<Box<dyn Foo>> it takes &Vec<Box<dyn Foo>>). Unfortunately, such impl doesn't exist, so it does the magic of autoref (part the process of trying to adjust a method receiver in Rust, you can read more here), and asks the same question for &&Vec<Box<dyn Foo>>. Now we did find a match - <&Vec<Box<dyn Foo>> as Clone>::clone()! So this is what the compiler calls.
What is the return type of the method? Well, &Vec<Box<dyn Foo>>. This will be the type of v_copy. Now we understand why when we specified another type, the compiler got crazy! We can also decrypt the error message when we didn't specify a type: we asked the compiler to call sort_by_key() on a &Vec<Box<dyn Foo>>, but this method requires a &mut Vec<Box<dyn Foo>> (&mut [Box<dyn Foo>], to be precise, but it doesn't matter because Vec<T> can coerce to [T])!
We can also understand the warning about a redundant mut: we never change the reference, so no need to declare it as mutable!
When we called to_vec(), OTOH, the compiler didn't get confused: to_vec() requires the vector's item to implement Clone (where T: Clone), which doesn't happen for Box<dyn Foo>. BOOM.
Now the solution should be clear: we just need Box<dyn Foo> to impl Clone.
Just?...
The first thing we may think about is to give Foo a supertrait Clone:
trait Foo: Clone {
fn value(&self) -> i32;
}
#[derive(Clone)]
struct Bar { /* ... */ }
Not working:
error[E0038]: the trait `Foo` cannot be made into an object
--> src/main.rs:33:31
|
33 | fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
| ^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:1:12
|
1 | trait Foo: Clone {
| --- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
Hmm, looks like Clone indeed requires Sized. Why?
Well, because in order to clone something, we need to return itself. Can we return dyn Foo? No, because it can be of any size.
So, let's try to impl Clone for Box<dyn Foo> by hand (we can do that even though Box is not defined in our crate because it is a fundamental type and Foo is local (defined in our crate)).
impl Clone for Box<dyn Foo> {
fn clone(self: &Box<dyn Foo>) -> Box<dyn Foo> {
// Now... What, actually?
}
}
How can we even clone something that can be anything? Clearly we need to forward it to someone else. Who else? Someone who knows how to clone this thing. A method on Foo?
trait Foo {
fn value(&self) -> i32;
fn clone_dyn(&self) -> Box<dyn Foo>;
}
impl Foo for Bar {
fn value(&self) -> i32 {
self.x
}
fn clone_dyn(&self) -> Box<dyn Foo> {
Box::new(self.clone()) // Forward to the derive(Clone) impl
}
}
NOW!
impl Clone for Box<dyn Foo> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}
IT WORKS!!
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d6e871711146bc3f34d9710211b4a1dd
Note: The dyn-clone crate from #dtonlay generalizes this idea.
You can make sort_and_print() shorter using Iterator::collect():
fn sort_and_print(v: &[Box<dyn Foo>]) {
let mut v_copy: Vec<_> = v.iter().collect();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Playground
As an aside, accepting a vector by reference is usually better expressed as accepting a slice, as explained here, so the above answer accepts a slice.
You can make it even shorter by using the sorted() method from the itertools crate, or in this case its cousin sorted_by_key():
use itertools::Itertools;
fn sort_and_print(v: &[Box<dyn Foo>]) {
for val in v.iter().sorted_by_key(|o| o.value()) {
println!("{}", val.value());
}
}
You almost certainly don't want to clone the vector because it would involve a deep copy, i.e. cloning each Box<dyn Foo>, which is unnecessary, potentially expensive, as well as complicated (as explained in the other answer).

Unboxing and inspecting a trait object

Here's a simple application that duplicates 2 times on stdout the contents of stdin:
use std::{
io,
io::{stdin, stdout, Read, Write},
num::NonZeroUsize,
};
fn dup_input(
input: &mut Box<dyn Read>,
output: &mut Box<dyn Write>,
count: NonZeroUsize,
) -> io::Result<()> {
let mut buf = Vec::new();
input.read_to_end(&mut buf)?;
for _idx in 0..count.get() {
output.write_all(&buf)?;
}
Ok(())
}
fn main() {
let mut input: Box<dyn Read> = Box::new(stdin());
let mut output: Box<dyn Write> = Box::new(stdout());
dup_input(&mut input, &mut output, NonZeroUsize::new(2).unwrap())
.expect("Failed to duplicate input");
}
This part works fine. I want to put a unit test on top of this and this is where the problem lies. The closest I've got to build is with the following attempt:
#[cfg(test)]
mod tests {
use super::*;
use std::{any::Any, io::Cursor};
#[test]
fn test() {
let mut input: Box<dyn Read> = Box::new(Cursor::new([b't', b'e', b's', b't', b'\n']));
let mut output: Box<dyn Write + Any> = Box::new(Vec::<u8>::new());
assert!(dup_input(&mut input, &mut output, NonZeroUsize::new(3).unwrap()).is_ok());
assert_eq!(output.downcast::<Vec<u8>>().unwrap().len(), 15);
}
}
but rust 1.41.0 doesn't agree:
$ cargo test
Compiling unbox-example v0.1.0 (/XXX/unbox-example)
error[E0225]: only auto traits can be used as additional traits in a trait object
--> src/main.rs:39:41
|
39 | let mut output: Box<dyn Write + Any> = Box::new(Vec::<u8>::new());
| ----- ^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| first non-auto trait
| trait alias used in trait object type (first use)
error[E0308]: mismatched types
--> src/main.rs:41:39
|
41 | assert!(dup_input(&mut input, &mut output, NonZeroUsize::new(3).unwrap()).is_ok());
| ^^^^^^^^^^^ expected trait `std::io::Write`, found a different trait `std::io::Write`
|
= note: expected mutable reference `&mut std::boxed::Box<(dyn std::io::Write + 'static)>`
found mutable reference `&mut std::boxed::Box<(dyn std::io::Write + 'static)>`
error[E0599]: no method named `downcast` found for type `std::boxed::Box<(dyn std::io::Write + 'static)>` in the current scope
--> src/main.rs:43:27
|
43 | assert_eq!(output.downcast::<Vec<u8>>().unwrap().len(), 15);
| ^^^^^^^^ method not found in `std::boxed::Box<(dyn std::io::Write + 'static)>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0225, E0308, E0599.
For more information about an error, try `rustc --explain E0225`.
error: could not compile `unbox-example`.
To learn more, run the command again with --verbose.
Is there a way to change the unit test without changing the main code? Note: I could have used generics while implementing dup_input and make the problem significantly easier to solve but this code is part of a broader application and I have to use Read/Write trait objects.
Passing a mutable reference to a Box to dup_input is unnecessarily complicated. You can simply pass a mutable reference to the trait object.
use std::{
io,
io::{stdin, stdout, Read, Write},
num::NonZeroUsize,
};
fn dup_input(
input: &mut dyn Read,
output: &mut dyn Write,
count: NonZeroUsize,
) -> io::Result<()> {
let mut buf = Vec::new();
input.read_to_end(&mut buf)?;
for _idx in 0..count.get() {
output.write_all(&buf)?;
}
Ok(())
}
fn main() {
let mut input = stdin();
let mut output = stdout();
dup_input(&mut input, &mut output, NonZeroUsize::new(2).unwrap())
.expect("Failed to duplicate input");
}
With this version, the test can be written like this:
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test() {
let mut input = Cursor::new([b't', b'e', b's', b't', b'\n']);
let mut output = Vec::<u8>::new();
assert!(dup_input(&mut input, &mut output, NonZeroUsize::new(3).unwrap()).is_ok());
assert_eq!(output.len(), 15);
}
}
We don't need to use Any at all here: output is simply a Vec<u8>.

Forcing a borrow with the `Into` trait

struct Foo(i32);
impl<'a> Into<i32> for &'a Foo {
fn into(self) -> i32 {
self.0
}
}
fn test<I: Into<i32>>(i: I) {
let n: i32 = i.into();
println!("{}", n);
}
fn main() {
let f = Foo(42);
test(&f);
}
playground
This works but just looking at test
fn test<I: Into<i32>>(i: I) {
let n: i32 = i.into();
println!("{}", n);
}
The function can access both a borrow and a move/copy depending on how the Into trait is implemented.
impl<'a> Into<i32> for &'a Foo
// vs
impl Into<i32> for Foo
Now the user could try to call test like test(f); instead of test(&f); and would receive the following error message.
error[E0277]: the trait bound `i32: std::convert::From<Foo>` is not satisfied
--> <anon>:16:5
|
16 | test(f);
| ^^^^ trait `i32: std::convert::From<Foo>` not satisfied
|
Would it be possible to always force a borrow? Something similar to this
fn test<I: Into<i32>>(i: &I) {
let n: i32 = i.into();
println!("{}", n);
}
So that the user would get an error message similar to, "Expected &XX but found YY".
A where-clause works here by specifying the lifetime:
fn test<'a, I>(i: &'a I) where &'a I: Into<i32> {
let n: i32 = i.into();
println!("{}", n);
}
Now when you attempt to build with test(f);, the message is clearer:
error[E0308]: mismatched types
--> src/main.rs:16:10
|
16 | test(f);
| ^
| |
| expected `&Foo`, found struct `Foo`
| help: consider borrowing here: `&f`

Resources