-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Use generic trait implementations for Cursor when possible. #27197
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
☔ The latest upstream changes (presumably #27219) made this pull request unmergeable. Please resolve the merge conflicts. |
0fc5b20
to
9cbb867
Compare
rebased |
@nwin, sorry for the reviewing delay -- I was away on vacation last week. This change looks good to me, but I'd also like to get @alexcrichton's opinion. We don't currently use |
I do feel somewhat more comfortable with this than before (using Unfortunately this also doesn't enable things like |
Do you remember what was holding back something like impl<T: ?Sized, V: AsRef<T> + ?Sized> AsRef<T> for Box<V> {
#[inline]
fn as_ref(&self) -> &T {
(&*self).as_ref()
}
} That would have been my next PR. |
I believe the killer aspect was that the meaning of |
Looks like this causes one regression on crates.io |
That breakage seems acceptable under our semver guidelines. @nwin, I'm wondering if you can elaborate on the motivation here. Is it mainly to clean up the implementation, or is there a use case you've run into that needs this additional flexibility? |
@alexcrichton Ah the @aturon As I already elaborated in #23364, my main motivation was to enable the usage of As it appears now, this is not so trivial but we are also in the unfortunate situation that it is currently impossible to write generic code over |
I updated this PR such that is uses |
9cbb867
to
7704ff1
Compare
Thanks @nwin! I'm on board with this change as-is, but I'm gonna flag this with |
The libs team discussed this during triage today, and the conclusion was that we're currently pretty on-the-fence about this. @gankro pointed out that the use of The conclusion was to reevaluate implementations of |
(note that Borrow isn't totally a collections thing today -- Cow being the notable exception) |
Ok, the crater report indicates a total of 5 root regressions, but 4 of those were timeouts (cc @brson, common to see?) and only one of them was related to the addition of cc #26096, the original issue about the regression. This may be showing up more externally than on crates.io as well because the use of smart pointers tends to happen more in apps than libs perhaps. |
@alexcrichton Yeah, timeouts are common. |
These common traits were left off originally by accident from these smart pointers, and a past attempt (rust-lang#26008) to add them was later reverted (rust-lang#26160) due to unexpected breakge (rust-lang#26096) occurring. The specific breakage in worry is the meaning of this return value changed: let a: Box<Option<T>> = ...; a.as_ref() Currently this returns `Option<&T>` but after this change it will return `&Option<T>` because the `AsRef::as_ref` method shares the same name as `Option::as_ref`. A [crater report][crater] of this change, however, has shown that the fallout of this change is quite minimal. These trait implementations are "the right impls to add" to these smart pointers and would enable various generalizations such as those in rust-lang#27197. [crater]: https://gist.github.com/anonymous/0ba4c3512b07641c0f99 This commit is a breaking change for the above reasons mentioned, and the mitigation strategies look like any of: Option::as_ref(&a) a.as_ref().as_ref() (*a).as_ref()
7704ff1
to
ea1f886
Compare
Great. I removed my latest commit and rebased onto master.
|
These common traits were left off originally by accident from these smart pointers, and a past attempt (#26008) to add them was later reverted (#26160) due to unexpected breakge (#26096) occurring. The specific breakage in worry is the meaning of this return value changed: let a: Box<Option<T>> = ...; a.as_ref() Currently this returns `Option<&T>` but after this change it will return `&Option<T>` because the `AsRef::as_ref` method shares the same name as `Option::as_ref`. A [crater report][crater] of this change, however, has shown that the fallout of this change is quite minimal. These trait implementations are "the right impls to add" to these smart pointers and would enable various generalizations such as those in #27197. [crater]: https://gist.github.com/anonymous/0ba4c3512b07641c0f99 This commit is a breaking change for the above reasons mentioned, and the mitigation strategies look like any of: Option::as_ref(&a) a.as_ref().as_ref() (*a).as_ref()
This is a revival of #23364. Github didn’t recognize my updated branch there. The cursor implementation now uses `AsRef` which means that fixed-sized array can now be used with `Cursor`. Besides that, the generic implementation simplifies the code as the macro can be avoided. The only drawback is, that specialized implementation for fixed-sized arrays are now ruled out unless [RFC#1210](rust-lang/rfcs#1210) is accepted & implemented. `Box<[u8]>` cannot be used yet, but that should be mitigated by [implementing `AsRef` for `Box` and friends](https://internals.rust-lang.org/t/forward-implement-traits-on-smart-pointers-make-smart-pointers-more-transparent/2380/3). I will submit a separate PR for that later as it is an orthogonal issue.
This introduces an unfortunate point of difference between futures::io::AsyncWrite and std::io::Write, but I think the increased ergonomics around writing to statically sized in memory buffers (presumably just for test purposes) is useful. `impl<T: AsRef<[u8]>> Read for Cursor<T>` was added in rust-lang/rust#27197, I'm not sure why `impl<T: AsMut<[u8]>> Write for Cursor<T>` wasn't added at the same time; I would propose doing this change in `std` and just piggybacking off it here, but the breakage is almost certainly not worth it by this point.
This introduces an unfortunate point of difference between `futures::io::AsyncWrite` and `std::io::Write`, but I think the increased ergonomics around writing to statically sized in memory buffers (presumably just for test purposes) is useful. `impl<T: AsRef<[u8]>> Read for Cursor<T>` was added in rust-lang/rust#27197, I'm not sure why `impl<T: AsMut<[u8]>> Write for Cursor<T>` wasn't added at the same time; I would propose doing this change in `std` and just piggybacking off it here, but the breakage is almost certainly not worth it by this point.
This introduces an unfortunate point of difference between `futures::io::AsyncWrite` and `std::io::Write`, but I think the increased ergonomics around writing to statically sized in memory buffers (presumably just for test purposes) is useful. `impl<T: AsRef<[u8]>> Read for Cursor<T>` was added in rust-lang/rust#27197, I'm not sure why `impl<T: AsMut<[u8]>> Write for Cursor<T>` wasn't added at the same time; I would propose doing this change in `std` and just piggybacking off it here, but the breakage is almost certainly not worth it by this point.
This introduces an unfortunate point of difference between `futures::io::AsyncWrite` and `std::io::Write`, but I think the increased ergonomics around writing to statically sized in memory buffers (presumably just for test purposes) is useful. `impl<T: AsRef<[u8]>> Read for Cursor<T>` was added in rust-lang/rust#27197, I'm not sure why `impl<T: AsMut<[u8]>> Write for Cursor<T>` wasn't added at the same time; I would propose doing this change in `std` and just piggybacking off it here, but the breakage is almost certainly not worth it by this point.
…lnay Implement `Write for Cursor<[u8; N]>`, plus `A: Allocator` cursor support This implements `Write for Cursor<[u8; N]>`, and also adds support for generic `A: Allocator` in `Box` and `Vec` cursors. This was inspired by a user questioning why they couldn't write a `Cursor<[u8; N]>`: https://users.rust-lang.org/t/why-vec-and-not-u8-makes-cursor-have-write/68210 Related history: - rust-lang#27197 switched `AsRef<[u8]>` for reading and seeking - rust-lang#67415 tried to use `AsMut<[u8]>` for writing, but did not specialize `Vec`.
…lnay Implement `Write for Cursor<[u8; N]>`, plus `A: Allocator` cursor support This implements `Write for Cursor<[u8; N]>`, and also adds support for generic `A: Allocator` in `Box` and `Vec` cursors. This was inspired by a user questioning why they couldn't write a `Cursor<[u8; N]>`: https://users.rust-lang.org/t/why-vec-and-not-u8-makes-cursor-have-write/68210 Related history: - rust-lang#27197 switched `AsRef<[u8]>` for reading and seeking - rust-lang#67415 tried to use `AsMut<[u8]>` for writing, but did not specialize `Vec`.
This is a revival of #23364. Github didn’t recognize my updated branch there.
The cursor implementation now uses
AsRef
which means that fixed-sized array can now be used withCursor
. Besides that, the generic implementation simplifies the code as the macro can be avoided.The only drawback is, that specialized implementation for fixed-sized arrays are now ruled out unless RFC#1210 is accepted & implemented.
Box<[u8]>
cannot be used yet, but that should be mitigated by implementingAsRef
forBox
and friends. I will submit a separate PR for that later as it is an orthogonal issue.