Skip to content

swap_unchecked ? #71874

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

Closed
leonardo-m opened this issue May 4, 2020 · 8 comments
Closed

swap_unchecked ? #71874

leonardo-m opened this issue May 4, 2020 · 8 comments
Labels
A-collections Area: `std::collections` C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@leonardo-m
Copy link

leonardo-m commented May 4, 2020

A slice method similar to slice::get_unchecked_mut that could be added:

#[inline]
pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
    unsafe {
        // Can't take two mutable loans from one vector, so instead
        // just cast them to their raw pointers to do the swap.
        let pa: *mut T = self.get_unchecked_mut(a);
        let pb: *mut T = self.get_unchecked_mut(b);
        ptr::swap(pa, pb);
    }
}

To be added to the std lib only if there's enough usage for this method.

See also:
https://crates.io/crates/unchecked-index

@bluss
Copy link
Member

bluss commented May 4, 2020

It is relatively easy to implement this outside of libcore (in your own code). The preferred way (current best practice) would be to go through self.as_mut_ptr() and offsetting from there, instead of calling get_unchecked_mut (which uses an exclusive borrow of the slice; no longer exclusive if we keep an active pointer around).

Use ```rust on your code fence to get syntax coloring.

@bluss bluss added A-collections Area: `std::collections` C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels May 4, 2020
@leonardo-m
Copy link
Author

leonardo-m commented May 4, 2020

Thank you for the comments bluss, second version then:

#[inline]
pub unsafe fn swap_unchecked(&mut self, i: usize, j: usize) {
    let ptr1 = self.as_mut_ptr().add(i);
    let ptr2 = self.as_mut_ptr().add(j);
    ptr::swap(ptr1, ptr2);
}

@bluss
Copy link
Member

bluss commented May 4, 2020

I'd propose this for anyone who wants to copy this implementation (this is what was meant with only using one &mut [T]).

// Method on [T]
pub unsafe fn swap_unchecked(&mut self, i: usize, j: usize) {
    debug_assert!(i < self.len());
    debug_assert!(j < self.len());
    let data_ptr = self.as_mut_ptr();
    std::ptr::swap(data_ptr.add(i), data_ptr.add(j));
}

@RalfJung
Copy link
Member

RalfJung commented May 5, 2020

@bluss maybe add a debug_assert!(i != j)?

@bluss
Copy link
Member

bluss commented May 5, 2020

For ptr::swap, equality is ok

@RalfJung
Copy link
Member

RalfJung commented May 5, 2020

Ah you are right.

@leonardo-m
Copy link
Author

@leonardo-m
Copy link
Author

Implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-collections Area: `std::collections` C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants