Skip to content

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

Closed
@nolanderc

Description

@nolanderc

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions