alloc: fix `Debug` implementation of `ExtractIf`
I noticed this while reviewing rust-lang/rust#141032. Calling `get` on the inner `Vec` never returns `Some` as the `Vec`'s length is temporarily set to zero while the `ExtractIf` exists.
Stabilize vec_into_raw_parts
This stabilizes `Vec::into_raw_parts()` and `String::into_raw_parts()` per FCP in https://github.com/rust-lang/rust/issues/65816#issuecomment-3517630971. While this _does not_ stabilize `Vec::into_parts()`, I fixed up the examples that said they were waiting for `vec_into_raw_parts`. As `Vec::from_parts()` and `Vec::into_parts()` are covered by the same feature `box_vec_non_null`, any doctest that uses `Vec::from_parts()` can also use `Vec::into_parts()` (and same for allocator-aware versions).
Closesrust-lang/rust#65816
``@rustbot`` modify labels: +T-libs-api
Expose fmt::Arguments::from_str as unstable.
Now that https://github.com/rust-lang/rust/pull/148789 is merged, we can have a fmt::Arguments::from_str. I don't know if we want to commit to always having an implementation that allows for this, but we can expose it as unstable for now so we can play with it.
Tracking issue: https://github.com/rust-lang/rust/issues/148905
stop specializing on `Copy`
fixes https://github.com/rust-lang/rust/issues/132442
`std` specializes on `Copy` to optimize certain library functions such as `clone_from_slice`. This is unsound, however, as the `Copy` implementation may not be always applicable because of lifetime bounds, which specialization does not take into account; the result being that values are copied even though they are not `Copy`. For instance, this code:
```rust
struct SometimesCopy<'a>(&'a Cell<bool>);
impl<'a> Clone for SometimesCopy<'a> {
fn clone(&self) -> Self {
self.0.set(true);
Self(self.0)
}
}
impl Copy for SometimesCopy<'static> {}
let clone_called = Cell::new(false);
// As SometimesCopy<'clone_called> is not 'static, this must run `clone`,
// setting the value to `true`.
let _ = [SometimesCopy(&clone_called)].clone();
assert!(clone_called.get());
```
should not panic, but does ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6be7a48cad849d8bd064491616fdb43c)).
To solve this, this PR introduces a new `unsafe` trait: `TrivialClone`. This trait may be implemented whenever the `Clone` implementation is equivalent to copying the value (so e.g. `fn clone(&self) -> Self { *self }`). Because of lifetime erasure, there is no way for the `Clone` implementation to observe lifetime bounds, meaning that even if the `TrivialClone` has stricter bounds than the `Clone` implementation, its invariant still holds. Therefore, it is sound to specialize on `TrivialClone`.
I've changed all `Copy` specializations in the standard library to specialize on `TrivialClone` instead. Unfortunately, the unsound `#[rustc_unsafe_specialization_marker]` attribute on `Copy` cannot be removed in this PR as `hashbrown` still depends on it. I'll make a PR updating `hashbrown` once this lands.
With `Copy` no longer being considered for specialization, this change alone would result in the standard library optimizations not being applied for user types unaware of `TrivialClone`. To avoid this and restore the optimizations in most cases, I have changed the expansion of `#[derive(Clone)]`: Currently, whenever both `Clone` and `Copy` are derived, the `clone` method performs a copy of the value. With this PR, the derive macro also adds a `TrivialClone` implementation to make this case observable using specialization. I anticipate that most users will use `#[derive(Clone, Copy)]` whenever both are applicable, so most users will still profit from the library optimizations.
Unfortunately, Hyrum's law applies to this PR: there are some popular crates which rely on the precise specialization behaviour of `core` to implement "specialization at home", e.g. [`libAFL`](89cff63702/libafl_bolts/src/tuples.rs (L27-L49)). I have no remorse for breaking such horrible code, but perhaps we should open other, better ways to satisfy their needs – for example by dropping the `'static` bound on `TypeId::of`...
Implement IsZero for ().
Implement default `IsZero` for all arrays, only returning true if the array is empty
(making the existing array impl for `IsZero` elements a specialization).
Optimize `IsZero::is_zero` for arrays of zero-sized `IsZero` elements.
add extend_front to VecDeque with specialization like extend
ACP: https://github.com/rust-lang/libs-team/issues/658
Tracking issue: rust-lang/rust#146975
_Text below was written before opening the ACP_
Feature was requested in rust-lang/rust#69939, I recently also needed it so decided to implement it as my first contribution to the Rust standard library. I plan on doing more but wanted to start with a small change.
Some questions I had (both on implementation and design) with answers:
- Q: `extend` allows iterators that yield `&T` where `T` is `Clone`, should extend_front do too?
A: No, users can use [`copied`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.copied) and/or [`cloned`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.cloned).
- Q: Does this need a whole new trait like Extend or only a method on `VecDeque`?
A: No, see ACP.
- Q: How do I deal with all the code duplication? Most code is similar to that of `extend`, maybe there is a nice way to factor out the code around `push_unchecked`/`push_front_unchecked`.
Will come back to this later.
- Q: Why are certain things behind feature gates, `cfg(not(test))` like `vec::IntoIter` here and `cfg(not(no_global_oom_handling))` like `Vec::extend_from_within`? (I am also looking at implementing `VecDeque::extend_from_within`)
A: See https://github.com/rust-lang/rust/pull/146861#pullrequestreview-3250163369
- Q: Should `extend_front` act like repeated pushes to the front of the queue? This reverses the order of the elements. Doing it different might incur an extra move if the iterator length is not known up front (where do you start placing elements in the buffer?).
A: `extend_front` acts like repeated pushes, `prepend` preserves the element order, see ACP or tracking issue.
Stabilize `fmt::from_fn`
Resolvesrust-lang/rust#146705, pending its FCP.
As discussed in that tracking issue and rust-lang/rust#117729, this splits `fmt::from_fn` out from the `debug_closure_helpers` feature.
Turn `Cow::is_borrowed,is_owned` into associated functions.
This is done because `Cow` implements `Deref`. Therefore, to avoid conflicts with an inner type having a method of the same name, we use an associated method, like `Box::into_raw`.
Tracking issue: #65143