Skip to content

Fix inconsistent safety requirement in VecDeque::nonoverlapping_ranges#158433

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
yilin0518:fix_nonoverlapping_ranges
Jun 28, 2026
Merged

Fix inconsistent safety requirement in VecDeque::nonoverlapping_ranges#158433
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
yilin0518:fix_nonoverlapping_ranges

Conversation

@yilin0518

Copy link
Copy Markdown
Contributor

The safety documentation of nonoverlapping_ranges says that its head argument must be in bounds:

    /// Get source, destination and count (like the arguments to [`ptr::copy_nonoverlapping`])
    /// for copying `count` values from index `src` to index `dst`.
    /// One of the ranges can wrap around the physical buffer, for this reason 2 triples are returned.
    ///
    /// Use of the word "ranges" specifically refers to `src..src + count` and `dst..dst + count`.
    ///
    /// # Safety
    ///
    /// - Ranges must not overlap: `src.abs_diff(dst) >= count`.
    /// - Ranges must be in bounds of the logical buffer: `src + count <= self.capacity()` and `dst + count <= self.capacity()`.
    /// - `head` must be in bounds: `head < self.capacity()`.
    #[cfg(not(no_global_oom_handling))]
    unsafe fn nonoverlapping_ranges(
        &mut self,
        src: usize,
        dst: usize,
        count: usize,
        head: usize,
    ) -> [(*const T, *mut T, usize); 2] {

However, this is slightly stricter than the VecDeque internal invariant for head. The struct-level invariant allows head == 0 when the buffer capacity is zero:

pub struct VecDeque<
    T,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
    // `self[0]`, if it exists, is `buf[head]`.
    // `head < buf.capacity()`, unless `buf.capacity() == 0` when `head == 0`.
    head: WrappedIndex,
    // the number of initialized elements, starting from the one at `head` and potentially wrapping around.
    // if `len == 0`, the exact value of `head` is unimportant.
    // if `T` is zero-Sized, then `self.len <= usize::MAX`, otherwise `self.len <= isize::MAX as usize`.
    len: usize,
    buf: RawVec<T, A>,
}

This zero-capacity case is reachable through the public API. I create the corresponding case in Rustplayground. This case can run without UB, also Miri runs successfully.

So it seems that the safety documentation of VecDeque::nonoverlapping_ranges is incorrect, or this API should add additional processing to approach this condition. This PR provides the minimal fix: updates the safety documentation for nonoverlapping_ranges to match the existing VecDeque invariant.

If needed, I can add a debug_assert! to check whether the input satisfies the requirement.

No behavior is changed.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 26, 2026
@rustbot

rustbot commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

r? @jhpratt

rustbot has assigned @jhpratt.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: libs
  • libs expanded to 12 candidates
  • Random selection from Darksonn, JohnTitor, Mark-Simulacrum, clarfonthey, jhpratt

@jhpratt

jhpratt commented Jun 28, 2026

Copy link
Copy Markdown
Member

Given that this is an internal API, this shouldn't need team approval.

@bors r+ rollup

@rust-bors

rust-bors Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 58f80da has been approved by jhpratt

It is now in the queue for this repository.

🌲 The tree is currently closed for pull requests below priority 2. This pull request will be tested once the tree is reopened.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 28, 2026
rust-bors Bot pushed a commit that referenced this pull request Jun 28, 2026
Rollup of 15 pull requests

Successful merges:

 - #158497 (stdarch subtree update)
 - #152225 (Add supertrait item shadowing for type-level path resolution)
 - #158194 (Adds RmetaLinkCache a per-link cache that uses path as the key of dec…)
 - #158466 (rustdoc: show impl Trait<Box<Local>> for Foreign, etc on Local's docs)
 - #158501 (miri subtree update)
 - #153097 (Expand `OptionFlatten`'s iterator methods)
 - #157614 (Move tests drop)
 - #157996 (perf: drop the full-crate AST walk in check_unused)
 - #158163 (Fix too-short variance slice in `variances_of` cycle recovery)
 - #158233 (Allow the unstable attribute on foreign type)
 - #158433 (Fix inconsistent safety requirement in VecDeque::nonoverlapping_ranges)
 - #158464 (Reorganize `tests/ui/issues` [15/N])
 - #158470 (Upgrade `jsonsocck` and `jsondoclint` to edition 2024.)
 - #158485 (Reorganize `tests/ui/issues` [16/N])
 - #158488 (Upgrade `rustdoc-json-types` to 2024 edition.)
@rust-bors rust-bors Bot merged commit d78d87a into rust-lang:main Jun 28, 2026
13 checks passed
@rustbot rustbot added this to the 1.98.0 milestone Jun 28, 2026
faukah pushed a commit to faukah/miri that referenced this pull request Jun 28, 2026
Rollup of 15 pull requests

Successful merges:

 - rust-lang/rust#158497 (stdarch subtree update)
 - rust-lang/rust#152225 (Add supertrait item shadowing for type-level path resolution)
 - rust-lang/rust#158194 (Adds RmetaLinkCache a per-link cache that uses path as the key of dec…)
 - rust-lang/rust#158466 (rustdoc: show impl Trait<Box<Local>> for Foreign, etc on Local's docs)
 - rust-lang/rust#158501 (miri subtree update)
 - rust-lang/rust#153097 (Expand `OptionFlatten`'s iterator methods)
 - rust-lang/rust#157614 (Move tests drop)
 - rust-lang/rust#157996 (perf: drop the full-crate AST walk in check_unused)
 - rust-lang/rust#158163 (Fix too-short variance slice in `variances_of` cycle recovery)
 - rust-lang/rust#158233 (Allow the unstable attribute on foreign type)
 - rust-lang/rust#158433 (Fix inconsistent safety requirement in VecDeque::nonoverlapping_ranges)
 - rust-lang/rust#158464 (Reorganize `tests/ui/issues` [15/N])
 - rust-lang/rust#158470 (Upgrade `jsonsocck` and `jsondoclint` to edition 2024.)
 - rust-lang/rust#158485 (Reorganize `tests/ui/issues` [16/N])
 - rust-lang/rust#158488 (Upgrade `rustdoc-json-types` to 2024 edition.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants