Skip to content
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

IoSlice: the Deref impl is too restrictive on the lifetime of the slice, an alternative is needed. #124659

Open
nolanderc opened this issue May 3, 2024 · 1 comment · May be fixed by #111277
Labels
C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@nolanderc
Copy link
Contributor

I tried code similar to the following to advance an std::io::IoSlice (playground link):

let mut buf = std::io::IoSlice::<'static>::new(b"foo");
let bytes: &[u8] = &buf;
let new_buf = std::io::IoSlice::new(&bytes[1..]);
buf = new_buf;

This does not compile, yielding the following error:

error[E0506]: cannot assign to `buf` because it is borrowed
 --> src/lib.rs:7:5
  |
5 |     let bytes: &[u8] = &buf;
  |                        ---- `buf` is borrowed here
6 |     let new_buf = std::io::IoSlice::new(&bytes[1..]);
7 |     buf = new_buf;
  |     ^^^^^^^^^^^^^
  |     |
  |     `buf` is assigned to here but it was already borrowed
  |     borrow later used here

The issue is that the Defer<Target = [u8]> impl on IoSlice discards the 'static lifetime, replacing it with the lifetime of the of buf.

However, we should be able to write such code using only safe Rust: all we are doing is effectively storing a subslice of the original buffer. For example, if we replace IoSlice with normal slices &[u8] it compiles:

let mut buf: &'static [u8] = b"foo";
let bytes: &[u8] = &buf;
let new_buf = &bytes[1..];
buf = new_buf;

To make IoSlice more flexible there should be a method which returns a slice with the same lifetime of the underlying memory, something similar to the following:

impl<'a> IoSlice<'a> {
    pub fn as_bytes(&self) -> &'a [u8] {
        // ...
    }
}

Note: this only applies to IoSlice, not IoSliteMut since it would break aliasing.

Meta

rustc --version --verbose:

rustc 1.78.0 (9b00956e5 2024-04-29)
binary: rustc
commit-hash: 9b00956e56009bab2aa15d7bff10916599e3d6d6
commit-date: 2024-04-29
host: x86_64-unknown-linux-gnu
release: 1.78.0
LLVM version: 18.1.2
@nolanderc nolanderc added the C-bug Category: This is a bug. label May 3, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 3, 2024
@nolanderc
Copy link
Contributor Author

Will be fixed by #111277

@saethlin saethlin added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 11, 2024
@saethlin saethlin linked a pull request May 11, 2024 that will close this issue
@tgross35 tgross35 linked a pull request Jul 17, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants