close
Skip to content

Implement VecDeque::truncate_to_range#156220

Open
cammeresi wants to merge 2 commits into
rust-lang:mainfrom
cammeresi:20260505-truncate-to-range
Open

Implement VecDeque::truncate_to_range#156220
cammeresi wants to merge 2 commits into
rust-lang:mainfrom
cammeresi:20260505-truncate-to-range

Conversation

@cammeresi
Copy link
Copy Markdown
Contributor

@cammeresi cammeresi commented May 6, 2026

Tracking issue: #156215

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 6, 2026
@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label May 6, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 6, 2026

r? @nia-e

rustbot has assigned @nia-e.
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 7 candidates
  • Random selection from Mark-Simulacrum, jhpratt, nia-e

Some(c) => {
let _g_a = Dropper(&mut *drop_a);
let _g_b = Dropper(&mut *drop_b);
ptr::drop_in_place(c);
Copy link
Copy Markdown
Contributor

@qaijuang qaijuang May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without dropper, won't this leak on panic ? same for line 1537

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would it panic? _g_{a,b} will only have their destructors run after we already attempt to drop c

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, i see

let bptr = back.as_mut_ptr();

unsafe {
let (drop_a, drop_b, drop_c) = if end <= flen {
Copy link
Copy Markdown
Contributor

@qaijuang qaijuang May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to add a fast path for types that don’t need dropping? Something like:

around line 1493

if !mem::needs_drop::<T>() {
    self.head = self.to_physical_idx(start);
    self.len = end - start;
    return;
}

what do you think ?

View changes since the review

@nia-e
Copy link
Copy Markdown
Member

nia-e commented May 12, 2026

See @qaijuang's point on checking for drop; otherwise, r=me

@nia-e nia-e added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 12, 2026
@cammeresi cammeresi force-pushed the 20260505-truncate-to-range branch from 8cab6b8 to ecb66eb Compare May 12, 2026 14:14
@nia-e
Copy link
Copy Markdown
Member

nia-e commented May 12, 2026

Could you also add a test for the drop impl? e.g.

// in a test fn

static DROPPED: AtomicUsize = AtomicUsize::new(0);

struct Foo(/* whatever */);

impl Drop for Foo {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Ordering::Relaxed);
    }
}

let mut dq = /* get a vecdeque of Foo, say 12 elems long */
dq.truncate_to_range(1..5);
assert_eq!(8, DROPPED.load(Ordering::Relaxed));

@cammeresi
Copy link
Copy Markdown
Contributor Author

I will make the requested updates, but I suspect LLVM could drop all the drop code since there would be no side effect. I also note that needs_drop is very lightly used in the library and essentially never to optimize collections like this. E.g. Vec::truncate does not do this, nor does VecDeque::truncate (which is what I was cribbing from).

@nia-e
Copy link
Copy Markdown
Member

nia-e commented May 12, 2026

True, but that sounds to me like it should be used more ^^ and this all is unlikely to be optimised away since the drop glue will be defined in the crate where the element type is defined, and thus may not get properly inlined

@cammeresi cammeresi force-pushed the 20260505-truncate-to-range branch from ecb66eb to 3167c69 Compare May 12, 2026 14:58
@cammeresi
Copy link
Copy Markdown
Contributor Author

This patch is now blocked behind the rename of truncate_front, so in the interim I examined what LLVM is actually capable of in terms of ellision.

I am able to report that the pessimism here is half right and half wrong.

In a release build, when calling regular truncate, the whole thing gets inlined and eliminated other than the length check and set. But debug mode doesn't do any of that and produces a whole bunch of instructions.

The location of the Point type seemed to make no difference. Moving it to an external crate did not change the assembly.

So do you actually want this call? Do you want more of them through all the collection types?

Sorry if I have, through any ignorance, failed to construct or analyze this properly.

use std::collections::VecDeque;

#[derive(Debug, Default)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

#[unsafe(no_mangle)]
pub fn truncate_point(d: &mut VecDeque<Point>, len: usize) {
    d.truncate(len);
}

fn main() {
    let mut d = VecDeque::new();
    d.push_back(Point::default());
    truncate_point(&mut d, 0);
    println!("{d:?}");
}
truncate_point:
    .cfi_startproc
    cmp rsi, qword ptr [rdi + 24]
    jae .LBB5_2
    mov qword ptr [rdi + 24], rsi
.LBB5_2:
    ret

@qaijuang
Copy link
Copy Markdown
Contributor

In a release build, when calling regular truncate, the whole thing gets inlined and eliminated other than the length check and set. But debug mode doesn't do any of that and produces a whole bunch of instructions.

Interesting, the elimination is real on release builds, i was able to reproduce(external crate included).

Safe to say, since the Dropper has no side effect, the !mem::needs_drop::<T>() is a no-op IMO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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.

4 participants