-
Notifications
You must be signed in to change notification settings - Fork 191
Introduce a new Buffer
trait.
#1290
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we go with this approach, I feel like there's a pretty good chance compiler folks will improve the error messages for us if we file bug reports. The story around passing in a mutable array but needing a slice instead has annoyed me for quite some time (I usually just as_mut_slice
everything). It was pretty confusing to figure out initially, so I'm sure better error messages would be welcome.
2b47fd2
to
e455b94
Compare
f2eaa94
to
2278976
Compare
Looking at our APIs, I think we'd want to consider adding uninit methods to roughly these methods (the filtering is not great, sorry): |
82314ff
to
dbdf6d6
Compare
Ok, I've now updated everything in rustix to use the new
I'm not opposed to having them use |
impl<T> Buffer<T> for &mut [MaybeUninit<T>] {} | ||
impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {} | ||
#[cfg(feature = "alloc")] | ||
impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure we want this one? I feel like that's almost always wrong and you meant to use spare capacity. Maybe there's a use case I'm missing?
// auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so that our users | ||
// don't have to add an extra `*` in these situations. | ||
#[cfg(feature = "alloc")] | ||
impl<T> private::Sealed<T> for &mut Vec<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems very footgunny... is the thinking that users might create a big buffer initialized to zero and then pass that in? I can see that making sense, but it still scares me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this because rustix's current APIs already support using Vec
like this, because Vec
has a DerefMut
to &mut [T]
. This just ensures that any existing users doing this don't need to add an extra *
to keep working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough
Thank you so much for polishing this idea! We'll see if the pitch forks come out, but I'm very excited that MaybeUninit is no longer a second class citizen. |
My thoughts on the APIs that weren't updated.
The "problem" here is that all of these methods grow the buffer that's passed in. So I think these methods are fundamentally different and thus there's no need to try and shoehorn them into using the buffer trait.
This seems fine because these APIs are like
I have no opinion on these right now. I agree that more thought will be needed, so punting and creating separate methods in 1.x and then fully replacing in a distant v2 seems fine. |
ebc5de6
to
9b60fbe
Compare
Buffer
trait.Buffer
trait.
I found another confusing error message when testing with this patch:
Offhand, I'm not sure what it means. The code is in https://github.com/sunfishcode/xattr (which is a fork of https://github.com/Stebalien/xattr with fixes for rustix 1.0.0). |
I found a way to work around that error in that particular case, so I'm going to merge this and proceed with the next prerelease. If that error or other confusing errors pop up in more places, we can reevaluate. |
This is now prereleased in rustix 1.0.0-prerelease.1. |
What was the fix to that error? My guess is that again you'd need to reborrow. |
The let mut event_buf = [MaybeUninit::<epoll::Event>::uninit(); 4];
let (events, _) = retry_on_intr(|| epoll::wait(epoll_fd, &mut event_buf, None)).unwrap();
I think you pretty much always want to ignore This works, and isn't too bad, though: let events = match epoll::wait(epoll_fd, &mut event_buf, None) {
Ok((events, _)) => events,
Err(Errno::INTR) => &mut [],
Err(e) => panic!("epoll::wait failed: {e}"),
}; |
Yup, it's the reborrow bug again. You need to use |
Here are the minimal repros for the two bugs we've found:
I'll see if I can start a zulip thread about improving this. |
Moving the |
This example gets the same error message as the error in |
I filed #1356 to add an example with standalone testcases of all the various interesting error messages we've seen with |
The snippet I posted uses As I said, it's not necessarily bad to have to use |
Add the error message described [here], and a workaround. [here]: #1290 (comment)
@kevinmehall Ah, thanks for pointing that out. I've now filed #1375 to add an example that uses |
Add the error message described [here], and a workaround. [here]: #1290 (comment)
@kevinmehall Ah, I didn't realize this was specific to the MaybeUninit variants. Indeed, this time the compilation error is correct in that it prevents a potential soundness issue if fn uh_oh(f: impl FnMut() -> T) -> (T, T) { (f(), f()) }
let mut event_buf = [MaybeUninit::<u8>::uninit(); 4];
let (mut_ref_one, mut_ref_two) = uh_oh(|| &mut event_buf); Honestly I wonder if we should just get rid of |
Agreed that |
I've now written a blog post about the |
Great blog post, thanks for sharing! |
I'm experimenting with a
Buffer
trait similar to #908, however I've run into a few problems. See the questions in examples/new_read.rs for details.@notgull @SUPERCILEX