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

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).

Related

Multiple mutable borrows in Rust

I'm playing around with building a very simple stack based evaluator in Rust. I want the user to be able to define functions later, so I'm storing all operators in a HashMap with closures as values.
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator<'a> {
stack: Vec<Value>,
ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)>,
}
impl<'a> Evaluator<'a> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)> = HashMap::new();
ops.insert("+".to_string(), &|stack: &'a mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
});
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&'a mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
I'm currently getting two errors:
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:34:17
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
34 | self.stack.push(n);
| ^^^^^^^^^^ second mutable borrow occurs here
...
38 | f(&mut self.stack);
| ------------------
| | |
| | first mutable borrow occurs here
| argument requires that `self.stack` is borrowed for `'a`
error[E0596]: cannot borrow `**f` as mutable, as it is behind a `&` reference
--> src/sample.rs:38:21
|
38 | f(&mut self.stack);
| ^ cannot borrow as mutable
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:38:23
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
38 | f(&mut self.stack);
| --^^^^^^^^^^^^^^^-
| | |
| | `self.stack` was mutably borrowed here in the previous iteration of the loop
| argument requires that `self.stack` is borrowed for `'a`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0499, E0596.
For more information about an error, try `rustc --explain E0499`.
My concern is the first one. I'm not sure what I'm doing wrong as I'm not borrowing them at the same time. Can I tell Rust the previous borrow (self.stack.pop()) is done? Any help appreciated.
I think I solved my problem. The thing I kept coming back to is, "What owns the closures?" In this case I'm using references, but nothing is taking ownership of the data. When I refactored (below) with Box to take ownership, it worked.
I'm curious if there is a way to do this with with just references and/or if my explanation is wrong?
Working code:
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator {
stack: Vec<Value>,
ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>>,
}
impl Evaluator {
pub fn new() -> Evaluator {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>> = HashMap::new();
ops.insert("+".to_string(), Box::new(|stack: &mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
}));
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get_mut(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
You have borrows with conflicting lifetimes:
You are defining a lifetime 'a for the struct in line 5: pub struct Evaluator<'a> {
In line 7, you are stating that ops is a HashMap that holds functions that receive mutable borrows for the whole duration of 'a
Then, in line 28, you are defining an eval method that holds a mutable reference to self for the whole duration of the struct ('a)
The conflict can be solved if you use two different lifetimes, since the time that an operation borrows self should be inherently shorter than the lifetime for the whole evaluation, since in eval you are running a loop and multiple invocations to the operations.
This should fix the issues mentioned above:
pub struct Evaluator<'a, 'b> {
stack: Vec<Value>,
ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)>,
}
impl<'a, 'b> Evaluator<'a, 'b> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)> = HashMap::new();

A struct with a trait field, but optional

Say I have a struct whose implementation writes somewhere, i.e. to something that implements the std::io::Write trait. However, I don't want the struct to own this. The following code works:
fn main() {
let mut out = std::io::stdout();
let mut foo = Foo::new(&mut out);
foo.print_number(2);
}
struct Foo<'a> {
out: &'a mut dyn std::io::Write
}
impl<'a> Foo<'a> {
pub fn new(out: &'a mut dyn std::io::Write) -> Self {
Self {
out
}
}
pub fn print_number(&mut self, i: isize) {
writeln!(self.out, "The number is {}", i).unwrap()
}
}
But, now this writing functionality should be made optional. I thought this sounds easy enough, but now the following doesn't compile:
fn main() {
let mut out = std::io::stdout();
let mut foo = Foo::new(Some(&mut out));
foo.print_number(2);
}
struct Foo<'a> {
out: Option<&'a mut dyn std::io::Write>
}
impl<'a> Foo<'a> {
pub fn new(out: Option<&'a mut dyn std::io::Write>) -> Self {
Self {
out
}
}
pub fn print_number(&mut self, i: isize) {
if self.out.is_some() {
writeln!(self.out.unwrap(), "The number is {}", i).unwrap()
}
}
}
because of:
error[E0507]: cannot move out of `self.out` which is behind a mutable reference
--> src/main.rs:20:26
|
20 | writeln!(self.out.unwrap(), "The number is {}", i).unwrap()
| ^^^^^^^^
| |
| move occurs because `self.out` has type `Option<&mut dyn std::io::Write>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `self.out.as_ref()`
which I'm not sure how to interpret.
I tried following the suggestion by changing the line in question to:
writeln!(self.out.as_ref().unwrap(), "The number is {}", i).unwrap()
but then I get
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:20:26
|
20 | writeln!(self.out.as_ref().unwrap(), "The number is {}", i).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
I'm really not sure how to interpret these error messages and surprisingly I'm not really getting anywhere by just sprinkling &s and muts in random places without really understanding!
(As an aside, I'm not sure if this is a "good" way of going about this anyway? I'm open to completely different approaches of solving this problem, which is basically to optionally pass something to write to into a struct, but without the struct owning it. I read about the Box type which might also be relevant?)
As you already know, based on you already using &mut for out. The issue with using as_ref() is that it returns an immutable reference. Instead you need to use as_mut().
pub fn print_number(&mut self, i: isize) {
if self.out.is_some() {
writeln!(self.out.as_mut().unwrap(), "The number is {}", i).unwrap()
}
}
Alternatively, you can also simplify this and express it more idiomatically using if let:
pub fn print_number(&mut self, i: isize) {
if let Some(out) = &mut self.out {
writeln!(out, "The number is {}", i).unwrap()
}
}
I would also suggest that instead of unwrapping, that you return the io::Result and let the caller handle any potential error.
pub fn print_number(&mut self, i: isize) -> std::io::Result<()> {
if let Some(out) = &mut self.out {
writeln!(out, "The number is {}", i)?;
}
Ok(())
}
You can also simplify your paths, e.g. std::io::Write and std::io::Result<()>, by importing them with a use declaration, e.g. use std::io::{self, Write}; and then changing them to Write and io::Result<()>.

understanding e0507 error and trying to resolve

I am in a &mut self function, I have a member field that is a Vec<u8>. I want to call a windows xxxA function (via the excellent winapi crate). I have no choice on the fn signature, it is implementing a trait.
I think I need to make a CString. So I tried
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
this doesn't work.
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\windbg.rs:51:36
|
51 | let str = CString::new(self.buf).unwrap();
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
I've read the explain of this but none of the 3 suggested solutions seem possible.
Here is the whole struct:
struct WinDbgWriter {
buf: Vec<u8>,
}
use std::io::Write;
impl std::io::Write for WinDbgWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
}
If we take your minimized case and try to borrow self.mut to avoid moving it (transferring its ownership), we get a new error which has a suggestion:
error[E0277]: the trait bound `Vec<u8>: From<&Vec<u8>>` is not satisfied
--> src/lib.rs:9:33
|
9 | let _str = CString::new(&self.buf).unwrap();
| ^^^^^^^^^
| |
| the trait `From<&Vec<u8>>` is not implemented for `Vec<u8>`
| help: consider adding dereference here: `&*self.buf`
|
= help: the following implementations were found:
<Vec<T> as From<&[T]>>
<Vec<T> as From<&mut [T]>>
<Vec<T> as From<BinaryHeap<T>>>
<Vec<T> as From<Box<[T]>>>
and 6 others
= note: required because of the requirements on the impl of `Into<Vec<u8>>` for `&Vec<u8>`
If we follow that suggestion, or explicitly coerce self.buf to a &[u8], then the code compiles.
CString::new takes an argument of some type Into<Vec<u8>>, but self.buf is, at this point of type &Vec<u8> because of it being accessed through a &self borrow, and there's no impl Into<Vec<u8>> for &Vec<u8>.

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

Why do `mut` and non-`mut` referrence fields have different lifetimes when returned from a getter? [duplicate]

This code works fine (Playground):
struct F<'a> {
x: &'a i32,
}
impl<'a> F<'a> {
fn get<'b>(&'b self) -> &'a i32 {
self.x
}
}
fn main() {
let x = 3;
let y = F { x: &x };
let z = y.get();
}
But when I change x to be a mutable reference instead (Playground):
struct Foo<'a> {
x: &'a mut i32, // <-- `mut` added
}
impl<'a> Foo<'a> {
fn get(&self) -> &'a i32 {
self.x
}
}
fn main() {
let mut x = 3; // <-- `mut` added
let y = Foo { x: &mut x }; // <-- `mut` added
let z = y.get();
}
I get this error:
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:7:9
|
7 | self.x
| ^^^^^^
|
note: ...the reference is valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> Foo<'a> {
| ^^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
--> src/main.rs:6:5
|
6 | / fn get(&self) -> &'a i32 {
7 | | self.x
8 | | }
| |_____^
Why does that happen? As far as I see it, nothing about the lifetimes has changed: all values/references still live exactly as long as in the first code snippet.
Why does the Rust compiler reject this implementation of get? Because it allows:
The following is a perfectly reasonable main, assuming that get compiles:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
Yet if get were to compile, this would be fine:
a does not borrow y because the lifetime is different
b "consumes" y (moving from y.x) but we do not reuse it after
So everything is fine, except that we now have a &i32 and &mut i32 both pointing to x.
Note: to make it compile, you can use unsafe inside of get: unsafe { std::mem::transmute(&*self.x) }; scary, eh?
At the heart of the borrow-checking algorithm is the cornerstone on which Rust's memory safety is built:
Aliasing XOR Mutability
Rust achieves memory safety without garbage collection by guaranteeing that whenever you are modifying something, no observer can have a reference inside that something that could become dangling.
This, in turns, lets us interpret:
&T as an aliasing reference; it is Copy
&mut T as a unique reference; it is NOT Copy, as it would violate uniqueness, but it can be moved
This difference saved us here.
Since &mut T cannot be copied, the only way to go from &mut T to &T (or &mut T) is to perform a re-borrowing: dereference and take a reference to the result.
This is done implicitly by the compiler. Doing it manually makes for a somewhat better error message:
fn get<'b>(&'b self) -> &'a i32 {
&*self.x
}
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:7:9
|
7 | &*self.x
| ^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn get(&'a self) -> &'a i32
--> <anon>:6:5
|
6 | fn get<'b>(&'b self) -> &'a i32 {
| ^
Why cannot it infer a lifetime? Because lifetime of the re-borrow is limited by 'b but we are requiring a 'a and there's no relationship between the two!
By the way, this is what is saving us from blunder here, because it ensures that the instance Foo must be borrowed while the result lives (preventing us to use a mutable reference via Foo::x).
Following the compiler hint, and returning &'b i32 works... and prevents the above main from compiling:
impl<'a> Foo<'a> {
fn get<'b>(&'b self) -> &'b i32 {
&*self.x
}
}
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
error[E0505]: cannot move out of `y.x` because it is borrowed
--> <anon>:16:9
|
15 | let a = y.get();
| - borrow of `y` occurs here
16 | let b = y.x;
| ^ move out of `y.x` occurs here
However it lets the first main compile without issue:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let z = y.get();
println!("{}", z);
}
Prints 3.

Resources