Change:
Rust PR: Standalone implementation: Summary: This is a safe wrapper around , for regions within a single slice. Previously, safe in-place copying was only available as a side effect of . Open questions: had a proposal for an alternative API using ranges. Here's an example PR along those lines: [x] implement as a PR () [x] land as unstable [x] decide on a final API [x] stabilize
what do the next steps look like for something like this? How do we "decide" on an API? :)
the process here is somewhat informal, but after the API has been in nightly for some time it's renominated for stabilization with any open questions, and at that point the libs team all signs off on the stabilization. To that end it's basically "let this sit for awhile and gain feedback", and then after awhile has passed it can be proposed to be stabilized
FWIW, I tried this out in ring and here's my feedback: I wish there was a non-panicking version that failed with an error result when the bounds are out of range. I ended up having to duplicate the range checking in my own code. It is very important that the implementation be inlined but the implementation doesn't have . In practice the compiler was always inlining it for me but it would be good to do something more to ensure this.
Thanks for trying it out. 's the situation where you need to check against making an out of bounds copy? Would it be possible to see the code where this came up? What fallback would you be using if copy_within returned an error?
I have my own API that is like , but which does an encryption/decryption operation as part of the copying, but my API avoids panicking on invalid bounds. There wouldn't be any fallback used; I just return an error.
I don't imagine it would make sense to hoist the bounds checking requirement up to the caller, and just have ring propagate the panic if the bounds are wrong? I guess the question is whether any of the callers are expected to have a fallback, or whether bad bounds are more likely to be programmer error.
There are lots of possibilities. This isn't the only API in libstd that has only a panicking version so if that's what libstd people like, I would just carry on as-is.
Yeah I was definitely working by analogy with and friends.
FWIW this is by crate. Currently is used to achieve this.
Adding sounds good, do you want to send a PR? The arguments for a non-panicking version also sound good to me. Perhaps even instead of, not in addition to what’s implemented today. And users that want panic can call . What API should this have? Perhaps a return type rather than to take advantage of , but there is no precedent in for , so with a new dedicated error type? The other API that does non-panicky bounds checking of a range argument is which returns an , but that one doesn’t have side effects and is only useful for its return value.
I put an change up as , but was opposed to it. There's some discussion in the PR. I feel like I remember some General Guidance from many years ago, when there was a big cleanup going on in the stdlib, about when to have panicking vs option/result APIs or when to have both. Does anyone remember where that was or what the consensus was there?
this function is available in the tiny  crate, if you want to keep the unsafe code out of the caller.
Has it been a while yet? :) I'd like to use this if stabilized.
Filed a stabilization PR at .

Discussion:
/// Copying four bytes within a slice: /// /// ``` <del> /// # #![feature(copy_within)] </del> /// let mut bytes = *b"Hello, World!"; /// /// bytes.copy_within(1..5, 8); /// /// assert_eq!(&bytes, b"Hello, Wello!"); /// ``` <del> #[unstable(feature = "copy_within", issue = "54236")] </del> <ins> #[stable(feature = "copy_within", since = "1.37.0")] </ins> pub fn copy_within<R: ops::RangeBounds<usize>>(&mut self, src: R, dest: usize) where T: Copy,

assert!(dest <= self.len() - count, "dest is out of bounds"); unsafe { ptr::copy( <del> self.get_unchecked(src_start), self.get_unchecked_mut(dest), </del> <ins> self.as_ptr().add(src_start), self.as_mut_ptr().add(dest), </ins> count, ); }

#![feature(inner_deref)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] <del> #![feature(copy_within)] </del> #![feature(int_error_matching)] #![feature(const_fn)] #![warn(rust_2018_idioms)]

let mut bytes = *b"Hello, World!"; bytes.copy_within(.., 0); assert_eq!(&bytes, b"Hello, World!"); <ins> // Ensure that copying at the end of slice won't cause UB. let mut bytes = *b"Hello, World!"; bytes.copy_within(13..13, 5); assert_eq!(&bytes, b"Hello, World!"); bytes.copy_within(5..5, 13); assert_eq!(&bytes, b"Hello, World!"); </ins> } #[test]

// 2 is greater than 1, so this range is invalid. bytes.copy_within(2..1, 0); } <ins> #[test] #[should_panic(expected = "attempted to index slice up to maximum usize")] fn test_copy_within_panics_src_out_of_bounds() { let mut bytes = *b"Hello, World!"; // an inclusive range ending at usize::max_value() would make src_end overflow bytes.copy_within(usize::max_value()..=usize::max_value(), 0); } </ins> #[test] fn test_is_sorted() {