I have a method which I want to give a Box which holds a struct that implements the std::io::Write trait. This is because in my program I want it to write to stdout, but in my tests I want it to write to a buffer and produce a string from that buffer to validate my program.
I am doing something like this in my program:
let stdOutWriter = Box::new(io::stdout());
write_output(&mut results, stdOutWriter);
where write_output calls:
let mut wtr = csv::Writer::from_writer(writer);
In my tests, I want to call:
let writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, writer).unwrap();
let bytes = Box::new(writer.into_inner().unwrap());
// I plan to validate this string later
let string = String::from_utf8(*bytes).unwrap();
The issue is that write_output consumes the writer, so I can't call writer.into_inner(). So I try to change it into a reference:
let mut writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, &mut writer).unwrap();
and now I get:
mismatched types expected mutable reference &mut Box<(dyn std::io::Write + 'static)>
found mutable reference &mut Box<BufWriter<Vec<u8>>>
How do I get around these issues?
edit:
The signature of write_output is:
fn write_output(results: &HashMap<u16, ResultRecord>,writer: &mut Box<dyn io::Write>) -> Result<(), Box<dyn Error>>
The function signature is unnecessarily constrained. In particular, &mut Box<dyn io::Write> also implements io::Write, so you could just as easily declare the type of the writer parameter to be impl io::Write. That would allow anything that satisfies &mut Box<dyn io::Write> and plenty more.
fn write_output(results: &HashMap<u16, ResultRecord>, writer: impl io::Write) -> Result<(), Box<dyn Error>>;
When you call it, you could pass a boxed writer:
let writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, writer);
Or a mutable reference to a boxed writer:
let mut writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, &mut writer);
Or any other writer:
let stderr = io::stderr();
let writer = stderr.lock();
write_output(&mut results, writer).unwrap();
Related
I'm trying to understand how to write a trait and an impl for it for my own types that will process some input data. I'm starting with a simple example where I want to process the input 1, 2, 3, 4 with a trait Processor. One implementation will skip the first element and double all remaining inputs. It should therefore look like this:
trait Processor {} // TBD
struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {} // TBD
let numbers = vec![1, 2, 3, 4];
let it = numbers.iter();
let it = Box::new(it);
let proc = SkipOneTimesTwo;
let four_to_eight = proc.process(it);
assert_eq!(Some(4), four_to_eight.next());
assert_eq!(Some(6), four_to_eight.next());
assert_eq!(Some(8), four_to_eight.next());
assert_eq!(None, four_to_eight.next());
So my assumption is that my trait and the corresponding implementation would look like this:
trait Processor {
// Arbitrarily convert from `i32` to `u32`
fn process(&self, it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>>;
}
struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {
fn process(&self, it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>> {
let p = it.skip(1).map(|i| 2 * (i as u32));
Box::new(p)
}
}
This code doesn't work as-is. I get the following error:
7 | let four_to_eight = proc.process(it);
| ^^ expected `i32`, found reference
|
= note: expected type `i32`
found reference `&{integer}`
= note: required for the cast to the object type `dyn Iterator<Item = i32>`
If my input data were very large, I wouldn't want the entire dataset to be kept in-memory (the whole point of using Iterator), so I assume that using Iterator<T> should stream data through from the original source of input until it is eventually aggregated or otherwise handled. I don't know what this means, however, in terms of what lifetimes I need to annotate here.
Eventually, my Processor may hold some intermediate data from the input (eg, for a running average calculation), so I will probably have to specify a lifetime on my struct.
Working with some of the compiler errors, I've tried adding 'a, 'static, and '_ lifetimes to my dyn Iterator<...>, but I can't quite figure out how to pass along an input iterator and modify the values lazily.
Is this even a reasonable approach? I could probably store the input Iterator<Item = i32> in my struct and impl Iterator<Item = u32> for SkipOneTimesTwo, but then I would presumably lose some of the abstraction of being able to pass around the Processor trait.
All iterators in Rust are lazy. Also, you don't need to use lifetimes, just use into_iter() instead of iter() and your code compiles:
trait Processor {
fn process(&self, it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>>;
}
struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {
fn process(&self, it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>> {
let p = it.skip(1).map(|i| 2 * (i as u32));
Box::new(p)
}
}
fn main() {
let numbers = vec![1, 2, 3, 4];
let it = numbers.into_iter(); // only change here
let it = Box::new(it);
let pro = SkipOneTimesTwo;
let mut four_to_eight = pro.process(it);
assert_eq!(Some(4), four_to_eight.next());
assert_eq!(Some(6), four_to_eight.next());
assert_eq!(Some(8), four_to_eight.next());
assert_eq!(None, four_to_eight.next());
}
playground
The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?
The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.
struct MutRef<'a> {
v: &'a mut i32
}
fn wrapper_use(s: MutRef) {
}
fn raw_use(s: &mut i32) {
}
fn raw_ref() {
let mut s: i32 = 9;
let q = &mut s;
raw_use(q);
raw_use(q);
}
fn wrapper() {
let mut s: i32 = 9;
let q = MutRef{ v: &mut s };
wrapper_use(q);
wrapper_use(q);
}
No.
The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.
You can always implement your own method to explicitly reborrow:
impl<'a> MutRef<'a> {
// equivalent to fn reborrow(&mut self) -> MutRef<'_>
fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
MutRef {v: self.v}
}
}
fn wrapper() {
let mut s: i32 = 9;
let mut q = MutRef{ v: &mut s };
wrapper_use(q.reborrow()); // does not move q
wrapper_use(q); // moves q
}
See also
Why is the mutable reference not moved here?
Type inference and borrowing vs ownership transfer
I've got a vector of reference-counted RefCells and want to pass a Vec of (mut) references into the RefCells into a function. The references shouldn't need to outlive the function call.
It seems like it should be possible (with just one, something like &*x.borrow_mut() is ok). I tried to keep intermediate vectors of RefMut and &mut to control the lifetimes, but I haven't yet worked out a way to get it to work:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a> {
pub r: &'a mut SomeTrait,
}
fn foo(_: &[Wrapper]) {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
foo(&v_wrapper[..]);
}
(playground)
There's clearly a lifetime issue:
rustc 1.11.0 (9b21dcd6a 2016-08-15)
error: borrowed value does not live long enough
--> <anon>:17:60
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^
note: reference must be valid for the block suffix following statement 2 at 17:107...
--> <anon>:17:108
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^
note: ...but borrowed value is only valid for the block at 17:71
--> <anon>:17:72
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
I do control foo so can alter its API to make things easier, but it's in a different module/crate and I don't really want it to need to know that I keep my SomeTrait objects in an Rc<RefCell<_>>.
While it is certainly possible to write code that starts with a Vec<RefMut<T>> and creates a Vec<&mut T> from that (generic example), I would suggest that you change the signature of foo. Many algorithms do not need the random access provided by slices, and if the function could accept an iterator instead of a slice, you wouldn't need to create two whole additional Vecs, aside from the calling function becoming simpler. I'm thinking of a signature like this
fn foo<I, R>(widgets: I)
where I: IntoIterator<Item=R>,
R: DerefMut<Target=SomeTrait>
{
for widget in widgets {
// ...
}
}
Then all you need is producing an iterator that yields RefMut's, which is easily accomplished with v1.iter_mut().map(|x| x.borrow_mut()). Here's an example.
First, I agree with #delnan that you should switch to an iterator-based interface if you can.
Most of this code is just fine, and after changing foo and Wrapper to be a bit more flexible, I was able to tweak the rest and get it to compile:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a, 'b> where 'b: 'a {
pub r: &'a mut (SomeTrait + 'b),
}
fn foo<'a, 'b>(_: &'a mut [Wrapper<'a, 'b>]) where 'b: 'a {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|mut rm| Wrapper{ r: &mut **rm }).collect();
foo(&mut v_wrapper[..]);
}
The key thing to understand here is that every trait object type has an implicit lifetime stapled to it, because an impl may contain references. There's no such type as SomeTrait, only SomeTrait + 'a or SomeTrait + 'b or SomeTrait + 'static.
The problem in your code was a mismatch between two things Rust inferred.
Where you wrote Rc<RefCell<SomeTrait>>, Rust assumed you meant Rc<RefCell<SomeTrait + 'static>>.
Where you wrote fn foo(_: &[Wrapper]) {}, different rules applied, and Rust assumed you meant fn foo<'a>(_: &'a [Wrapper<'a> + 'a]).
D'oh. Under those assumptions, the puzzle indeed has no solutions, and that's why I had to loosen things up.
If you don't want that 'b lifetime parameter, you can ditch it and just change 'b to 'static in the one place where it's used (on the type of Wrapper::r). That's less flexible: you'll be limited to SomeTrait impls that have static lifetime.
I have a bit of code that I'm fighting with. It's a little helper function that should return a Vec<&str> to the calling function. I can't seem to get the lifetime right, though.
Here is the code snippet:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> &'a mut TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
&mut out
}
The compiler is telling me: error: 'out' does not live long enough and that the reference must be valid for the lifetime of 'a, but it looks to me like it is defined for 'a.
I have also tried changing it to:
let out = &mut TokenList::<'a>::new();
which doesn't change any of the error messages. Or:
let out = &'a mut TokenList::<'a>::new();
which the compiler doesn't like at all.
How do I define out to have a lifetime of 'a?
For further details, here is my definition of TokenList:
pub type Token<'a> = &'a str;
pub type TokenList<'a> = Vec<Token<'a>>;
The lifetime of out is not 'a, since out is destroyed at the end of the function. Rust will not allow you to return a reference to it (it would allow accessing freed memory!).
Try changing your function to the following:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
out
}
This way you will pass the ownership of out to the caller and it will live long enough.
Can somebody help me to rewrite this piece of code with new unboxed closures:
struct Builder;
pub fn build(rules: |params: &mut Builder|) -> Builder {
let mut builder = Builder::new();
rules(&mut builder);
builder
}
I tried to write like this, but I got a lifetime error:
pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,), ()> {
let mut builder = Builder::new();
rules(&mut builder);
builder
}
valico/src/builder.rs:48:59: 48:71 error: missing lifetime specifier [E0106]
valico/src/builder.rs:48 pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,), ()> {
^~~~~~~~~~~~
What lifetime I need to specify? Simplified example in the sandbox.
This requires higher rank trait bounds, specifically, higher rank lifetimes. The full unsugared syntax would be F: for<'a> FnOnce<(&'a mut Builder,), ()>.
Using a lifetime on the function can't work, e.g. if we had
pub fn build<'b, F>(rules: F) -> Builder where F: FnOnce<(&'b mut Builder,), ()>
This says that build works with whatever lifetime the caller wishes (e.g. they could chose 'b == 'static), but this is invalid, because there is a specific concrete lifetime that needs to be the used: the lifetime of the &mut builder inside the function. Using F: for<'a> ... in a bound says that F works with any lifetime 'a, so the compiler sees that it is legal to substitute in the one of &mut builder.
As I hinted above, that's the really ugly unsugared syntax. There's two successive ways this can be made much nicer. Firstly, the canonical way to use the closure traits is the () sugar: for<'a> FnOnce(&'a mut Builder) -> (), or, like with the rest of Rust, the -> () can be dropped: for<'a> FnOnce(&'a mut Builder). (NB. this is just sugar for FnOnce<...>, but only the sugared syntax will be stabilised for interacting with these traits at 1.0.)
Then, the paren syntax has a little extra rule: it automatically inserts lifetimes that act like for<'a> (specifically, it undergoes lifetime elision with any inserted lifetime placed into a for on the trait), so just F: FnOnce(&mut Builder) is equivalent to F: for<'a> FnOnce(&'a mut Builder), and it's the recommended version.
Applying these fixes to your playpen example:
pub fn initialize_with_closure<F>(rules: F) -> uint where F: FnOnce(&mut uint) {
let mut i = 0;
rules(&mut i);
i
}
// equivalently
pub fn initialize_with_closure_explicit<F>(rules: F) -> uint where F: for<'a> FnOnce(&'a mut uint) -> () {
let mut i = 0;
rules(&mut i);
i
}
pub fn main() {
initialize_with_closure(|i: &mut uint| *i = *i + 20);
initialize_with_closure_explicit(|i: &mut uint| *i = *i + 20);
}
playpen