New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
write_message
now takes ownership of the Write
argument
#195
Comments
There is a blanket impl like this
so it should work for you to do |
Alas, no. If you just change the call to 17 | pub fn transcode<I,O>(input: I, output: &mut O, packed: bool)
| ------ help: consider changing this to be mutable: `mut output`
...
28 | write_message(&mut output, &bin)?
| ^^^^^^^^^^^ cannot borrow as mutable If 28 | write_message(&mut output, &bin)?
| ^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop |
Wow, interesting. I was able to replicate the error. The error goes away if I directly use
I tried manually annotating the type of the local |
I recommend working around this problem by doing this in the inner loop:
I'm not sure if there's a better way. |
Moving the selection into the inner loop and calling the right function directly doesn't work for similar reasons: pub fn transcode<I,O>(input: I, output: &mut O, packed: bool)
-> Result<(),Box<dyn Error>>
where I: Read, O: Write
{
let input = BufReader::new(input);
for line in input.lines() {
let line = line?;
let e: Event = serde_json::from_str(&line)?;
let bin = e.to_capnp();
if packed {
serialize_packed::write_message(output, &bin)?;
} else {
serialize::write_message(output, &bin)?;
};
}
Ok(())
} results in 17 | pub fn transcode<I,O>(input: I, output: &mut O, packed: bool)
| ------ move occurs because `output` has type `&mut O`, which does not implement the `Copy` trait
...
27 | serialize_packed::write_message(output, &bin)?;
| ^^^^^^ value moved here, in previous iteration of loop
28 | } else {
29 | serialize::write_message(output, &bin)?;
| ------ value moved here, in previous iteration of loop The Changing the function to take ownership of the pub fn transcode<I,O>(input: I, mut output: O, packed: bool)
-> Result<(),Box<dyn Error>>
where I: Read, O: Write
{
let input = BufReader::new(input);
for line in input.lines() {
let line = line?;
let e: Event = serde_json::from_str(&line)?;
let bin = e.to_capnp();
if packed {
serialize_packed::write_message(&mut output, &bin)?;
} else {
serialize::write_message(&mut output, &bin)?;
};
}
Ok(())
} But now the function can't be used if the caller is not willing to give up ownership of the Seem like a step back in usability and should probably be considered a breaking change. |
Does it work to call the pub fn transcode<I,O>(input: I, mut output: &mut O, packed: bool)
-> Result<(),Box<dyn Error>>
where I: Read, O: Write
{
let input = BufReader::new(input);
for line in input.lines() {
let line = line?;
let e: Event = serde_json::from_str(&line)?;
let bin = e.to_capnp();
if packed {
serialize_packed::write_message(&mut output, &bin)?;
} else {
serialize::write_message(&mut output, &bin)?;
};
}
Ok(())
} |
It does! I'll admit, I am not entirely sure what is going on there. |
I suppose making |
Another thing you could do is write your own little wrapper functions, like this: fn write_message_wrapper<W, A>(write: &mut W, message: &capnp::message::Builder<A>) -> capnp::Result<()>
where W: capnp::Write, A: capnp::message::Allocator {
capnp::serialize::write_message(write, message)
}
fn write_message_packed_wrapper<W, A>(write: &mut W, message: &capnp::message::Builder<A>) -> capnp::Result<()>
where W: capnp::Write, A: capnp::message::Allocator {
capnp::serialize_packed::write_message(write, message)
} Then your pub fn transcode<I,O>(input: I, output: &mut O, packed: bool)
-> Result<(),Box<dyn Error>>
where I: Read, O: Write
{
let write_message = if packed { write_message_packed_wrapper } else { write_message_wrapper };
let input = BufReader::new(input);
for line in input.lines() {
let line = line?;
let e: Event = serde_json::from_str(&line)?;
let bin = e.to_capnp();
write_message(output, &bin)?;
}
Ok(())
} That being said, it's unfortunate that we need to resort to this kind of workaround. When I made the change to the signature of I wonder if this should be considered a bug in the borrow checker. |
I asked about this on the rust-lang zulip: https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/surprising.20borrow.20checker.20behavior/near/203602445 Reportedly, the reason that the new |
On Zulip, eddyb suggested this way to avoid defining wrapper functions: pub fn transcode<I,O>(input: I, output: &mut O, packed: bool)
-> Result<(),Box<dyn Error>>
where I: Read, O: Write
{
let write_message : fn(&mut O, &_) -> capnp::Result<()> =
if packed {
|w, m| serialize_packed::write_message(w, m)
} else {
|w, m| serialize::write_message(w, m)
};
let input = BufReader::new(input);
for line in input.lines() {
let line = line?;
let e: Event = serde_json::from_str(&line)?;
let bin = e.to_capnp();
write_message(output, &bin)?;
}
Ok(())
} |
Thanks for the suggestion. |
I think this issue is fixed and can thus be closed, right? |
I suppose? There is a work around, although the original issue still stands. |
I would think #195 (comment) is basically the way I would recommend to solve this if it appears elsewhere (e.g. as this is the way it is handled with |
I considered going back to the old type signatures in the 0.14 release, but it wasn't quite as simple as I had hoped (because of the no-std stuff added in the 0.13 release). I think it might still make sense to go back to the old signatures in a future release, if we can find a simple and minimally disruptive way to do so. |
A recent commit changed
write_message
inserialize.rs
fromto
I am wondering why this changed.
It means you can no longer call
write_message
in a loop with a reference to aWrite
. E.g.Now gives an error:
The text was updated successfully, but these errors were encountered: