Make Read and BufRead dyn compatible#3917
Make Read and BufRead dyn compatible#3917tcharding wants to merge 1 commit intorust-bitcoin:masterfrom
Read and BufRead dyn compatible#3917Conversation
|
Might've been a MSRV thing. |
|
Oh, wait, this is about adding a Doesn't removing this bound break reading from |
hmmm, bother. I had wondered the same thing but was just lazy and cargo cult programmed based or Rust stdlib types. I'll put some more thought into this. |
|
I still don't know why use std::io::Read;
fn main() -> anyhow::Result<()> {
let data = [0x1_u8; 8];
let mut reader = &data[..4];
// Use the reader without mutating it, second read reads same data again.
use_sized_reader(reader)?;
use_sized_reader(reader)?;
// Use the reader while mutating it, second read reads no data.
use_sized_reader(&mut reader)?;
use_sized_reader(&mut reader)?;
let mut reader = &data[..4];
// Use the reader without mutating it, second read reads same data again.
// This does not build.
// use_unsized_reader(reader)?;
// use_unsized_reader(reader)?;
// Use the reader while mutating it, second read reads no data.
use_unsized_reader(&mut reader)?;
use_unsized_reader(&mut reader)?;
Ok(())
}
// From Rust docs: https://rust-lang.github.io/api-guidelines/interoperability.html#c-rw-value
//
// > That means any function that accepts R: Read or W: Write generic parameters by value can be called with a mut reference if necessary.
fn use_sized_reader<R: Read>(mut r: R) -> anyhow::Result<()> {
let mut buf = [0_u8; 16];
r.read(&mut buf)?;
println!("{:?}", buf);
Ok(())
}
fn use_unsized_reader<R: Read + ?Sized>(r: &mut R) -> anyhow::Result<()> {
let mut buf = [0_u8; 16];
r.read(&mut buf)?;
println!("{:?}", buf);
Ok(())
}Outputs [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]This also begs the question is the |
|
The problem occurs because these methods take |
|
So we have to make a trade off then. Either we cannot make our I clearly don't understand all the subtlety between |
|
I'm not understanding why one would need to be able to do the first two calls here when we can do either of the second two? I.e. when is the more general // First two don't build.
// use_sized_reader(data[..4])?;
// use_sized_reader(&mut data[..4])?;
use_sized_reader(&mut &data[..4])?;
use_sized_reader(&data[..4])?; |
|
EDIT: I deleted this post FYI |
We may be able to put the bound only on the
|
|
Hah! commit log fail - thanks for pulling me up.
We can't do that without changing What we could do is have a PR that discusses and tackles the |
|
We should PR to change the bitcoin methods first, and provide some justification there that we're not breaking stuff. (It sounds like the extra |
Kixunil
left a comment
There was a problem hiding this comment.
You must be confused somehow. Only adding the bound to take should be required. The code that needs to call take on trait objects can just use .by_ref().take(). But LMK if I'm missing something.
bitcoin/src/bip152.rs
Outdated
There was a problem hiding this comment.
NACK, this is a needless breaking change.
io/src/lib.rs
Outdated
There was a problem hiding this comment.
You should be able to call take() on &mut R, so this is not needed.
There was a problem hiding this comment.
I had two goes and couldn't work it out.
There was a problem hiding this comment.
Oh, that's because of the missing impl. We need to have type ByRef<'a, R> = &'a mut R in some future release. Anyway, ByRef should work for now.
api/io/no-features.txt
Outdated
There was a problem hiding this comment.
Whaaat? You reintroduced these... :(
There was a problem hiding this comment.
You weren't around to write the tooling required to run cargo public-api in CI so we could use the output without committing the files. And I couldn't be bothered to ...
Ah, derp, I should've thought of this. |
|
lol, I literally said above "why would anyone need |
Currently our `Read` and `BufRead` traits are not dyn compatible (object safe) because of `Take` having an unsized trait bound. We just removed the requirement for this by removing the bound from `consensus_encode`. Remove the `?Sized` trait bound from `Take` and add a test that shows that `Read` and `BufRead` are now dyn compatible. Fix: rust-bitcoin#3833
e587be8 to
c588053
Compare
|
We don't have |
c588053 to
940d947
Compare
Oh, I thought my PR got merged. I strongly suspect it also addressed the same issue you're trying to address here as I remember doing stuff around
Whaaat?! Looks like an oversight in |
|
I'm ok with deviating from std to drop the Edit actually, is the |
|
I'm struggling to see why we should provide an |
|
No need to answer me if #3945 is possible. |
|
@apoelstra
We shouldn't and nobody is proposing that. |
We're not -- we're proposing that the Then our consensus encoding code won't need a sized bound. |
And we construct in manually instead of using |
|
We have a couple choices:
|
|
I think this order makes most sense:
This should be it and nothing else should be needed. |
|
No sweat, I'm on it. |
|
Closing, |
In order to do this we need to remove the
?Sizedtrait bound fromconsensus_encode- done in patch 1. Please note I do not know why we added it in the first place (added in #1035).Patch 2 fixes
Takeand adds a unit test to verify alliotraits are dyn compatible (object safe).Close: #3833