Stabilize associated type bounds (RFC 2289)
This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses.
### What are we stabilizing?
We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation.
In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info).
Associated type bounds are stabilized in four positions:
* **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`.
* **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629.
* **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`.
* **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound.
The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds.
### How does this differ from the RFC?
Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular:
* It does *not* desugar to anonymous associated items in associated type item bounds.
* It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds.
This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example:
* Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531.
* Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types.
This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719.
### Implementation history:
Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out--
* #57428
* #108063
* #110512
* #112629
* #120719
* #120584Closes#52662
[RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
Vec::try_with_capacity
Related to #91913
Implements try_with_capacity for `Vec`, `VecDeque`, and `String`. I can follow it up with more collections if desired.
`Vec::try_with_capacity()` is functionally equivalent to the current stable:
```rust
let mut v = Vec::new();
v.try_reserve_exact(n)?
```
However, `try_reserve` calls non-inlined `finish_grow`, which requires old and new `Layout`, and is designed to reallocate memory. There is benefit to using `try_with_capacity`, besides syntax convenience, because it generates much smaller code at the call site with a direct call to the allocator. There's codegen test included.
It's also a very desirable functionality for users of `no_global_oom_handling` (Rust-for-Linux), since it makes a very commonly used function available in that environment (`with_capacity` is used much more frequently than all `(try_)reserve(_exact)`).
Remove special-case handling of `vec.split_off(0)`
#76682 added special handling to `Vec::split_off` for the case where `at == 0`. Instead of copying the vector's contents into a freshly-allocated vector and returning it, the special-case code steals the old vector's allocation, and replaces it with a new (empty) buffer with the same capacity.
That eliminates the need to copy the existing elements, but comes at a surprising cost, as seen in #119913. The returned vector's capacity is no longer determined by the size of its contents (as would be expected for a freshly-allocated vector), and instead uses the full capacity of the old vector.
In cases where the capacity is large but the size is small, that results in a much larger capacity than would be expected from reading the documentation of `split_off`. This is especially bad when `split_off` is called in a loop (to recycle a buffer), and the returned vectors have a wide variety of lengths.
I believe it's better to remove the special-case code, and treat `at == 0` just like any other value:
- The current documentation states that `split_off` returns a “newly allocated vector”, which is not actually true in the current implementation when `at == 0`.
- If the value of `at` could be non-zero at runtime, then the caller has already agreed to the cost of a full memcpy of the taken elements in the general case. Avoiding that copy would be nice if it were close to free, but the different handling of capacity means that it is not.
- If the caller specifically wants to avoid copying in the case where `at == 0`, they can easily implement that behaviour themselves using `mem::replace`.
Fixes#119913.
Add lint against ambiguous wide pointer comparisons
This PR is the resolution of https://github.com/rust-lang/rust/issues/106447 decided in https://github.com/rust-lang/rust/issues/117717 by T-lang.
## `ambiguous_wide_pointer_comparisons`
*warn-by-default*
The `ambiguous_wide_pointer_comparisons` lint checks comparison of `*const/*mut ?Sized` as the operands.
### Example
```rust
let ab = (A, B);
let a = &ab.0 as *const dyn T;
let b = &ab.1 as *const dyn T;
let _ = a == b;
```
### Explanation
The comparison includes metadata which may not be expected.
-------
This PR also drops `clippy::vtable_address_comparisons` which is superseded by this one.
~~One thing: is the current naming right? `invalid` seems a bit too much.~~
Fixes https://github.com/rust-lang/rust/issues/117717
detects redundant imports that can be eliminated.
for #117772 :
In order to facilitate review and modification, split the checking code and
removing redundant imports code into two PR.
Add support for making lib features internal
We have the notion of an "internal" lang feature: a feature that is never intended to be stabilized, and using which can cause ICEs and other issues without that being considered a bug.
This extends that idea to lib features as well. It is an alternative to https://github.com/rust-lang/rust/pull/115623: instead of using an attribute to declare lib features internal, we simply do this based on the name. Everything ending in `_internals` or `_internal` is considered internal.
Then we rename `core_intrinsics` to `core_intrinsics_internal`, which fixes https://github.com/rust-lang/rust/issues/115597.
Expand in-place iteration specialization to Flatten, FlatMap and ArrayChunks
This enables the following cases to collect in-place:
```rust
let v = vec![[0u8; 4]; 1024]
let v: Vec<_> = v.into_iter().flatten().collect();
let v: Vec<Option<NonZeroUsize>> = vec![NonZeroUsize::new(0); 1024];
let v: Vec<_> = v.into_iter().flatten().collect();
let v = vec![u8; 4096];
let v: Vec<_> = v.into_iter().array_chunks::<4>().collect();
```
Especially the nicheful-option-flattening should be useful in real code.
Implement iterator specialization traits on more adapters
This adds
* `TrustedLen` to `Skip` and `StepBy`
* `TrustedRandomAccess` to `Skip`
* `InPlaceIterable` and `SourceIter` to `Copied` and `Cloned`
The first two might improve performance in the compiler itself since `skip` is used in several places. Constellations that would exercise the last point are probably rare since it would require an owning iterator that has references as Items somewhere in its iterator pipeline.
Improvements for `Skip`:
```
# old
test iter::bench_skip_trusted_random_access ... bench: 8,335 ns/iter (+/- 90)
# new
test iter::bench_skip_trusted_random_access ... bench: 2,753 ns/iter (+/- 27)
```
Implement `From<{&,&mut} [T; N]>` for `Vec<T>` where `T: Clone`
Currently, if `T` implements `Clone`, we can create a `Vec<T>` from an `&[T]` or an `&mut [T]`, can we also support creating a `Vec<T>` from an `&[T; N]` or an `&mut [T; N]`? Also, do I need to add `#[inline]` to the implementation?
ACP: rust-lang/libs-team#220. [Accepted]
Closes#100880.
Don't panic in ceil_char_boundary
Implementing the alternative mentioned in this comment: https://github.com/rust-lang/rust/issues/93743#issuecomment-1579935853
Since `floor_char_boundary` will always work (rounding down to the length of the string is possible), it feels best for `ceil_char_boundary` to not panic either. However, the semantics of "rounding up" past the length of the string aren't very great, which is why the method originally panicked in these cases.
Taking into account how people are using this method, it feels best to simply return the end of the string in these cases, so that the result is still a valid char boundary.
Eliminate ZST allocations in `Box` and `Vec`
This PR fixes 2 issues with `Box` and `RawVec` related to ZST allocations. Specifically, the `Allocator` trait requires that:
- If you allocate a zero-sized layout then you must later deallocate it, otherwise the allocator may leak memory.
- You cannot pass a ZST pointer to the allocator that you haven't previously allocated.
These restrictions exist because an allocator implementation is allowed to allocate non-zero amounts of memory for a zero-sized allocation. For example, `malloc` in libc does this.
Currently, ZSTs are handled differently in `Box` and `Vec`:
- `Vec` never allocates when `T` is a ZST or if the vector capacity is 0.
- `Box` just blindly passes everything on to the allocator, including ZSTs.
This causes problems due to the free conversions between `Box<[T]>` and `Vec<T>`, specifically that ZST allocations could get leaked or a dangling pointer could be passed to `deallocate`.
This PR fixes this by changing `Box` to not allocate for zero-sized values and slices. It also fixes a bug in `RawVec::shrink` where shrinking to a size of zero did not actually free the backing memory.
Spelling library
Split per https://github.com/rust-lang/rust/pull/110392
I can squash once people are happy w/ the changes. It's really uncommon for large sets of changes to be perfectly acceptable w/o at least some changes.
I probably won't have time to respond until tomorrow or the next day
Partial stabilization of `once_cell`
This PR aims to stabilize a portion of the `once_cell` feature:
- `core::cell::OnceCell`
- `std::cell::OnceCell` (re-export of the above)
- `std::sync::OnceLock`
This will leave `LazyCell` and `LazyLock` unstabilized, which have been moved to the `lazy_cell` feature flag.
Tracking issue: https://github.com/rust-lang/rust/issues/74465 (does not fully close, but it may make sense to move to a new issue)
Future steps for separate PRs:
- ~~Add `#[inline]` to many methods~~ #105651
- Update cranelift usage of the `once_cell` crate
- Update rust-analyzer usage of the `once_cell` crate
- Update error messages discussing once_cell
## To be stabilized API summary
```rust
// core::cell (in core/cell/once.rs)
pub struct OnceCell<T> { .. }
impl<T> OnceCell<T> {
pub const fn new() -> OnceCell<T>;
pub fn get(&self) -> Option<&T>;
pub fn get_mut(&mut self) -> Option<&mut T>;
pub fn set(&self, value: T) -> Result<(), T>;
pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T;
pub fn into_inner(self) -> Option<T>;
pub fn take(&mut self) -> Option<T>;
}
impl<T: Clone> Clone for OnceCell<T>;
impl<T: Debug> Debug for OnceCell<T>
impl<T> Default for OnceCell<T>;
impl<T> From<T> for OnceCell<T>;
impl<T: PartialEq> PartialEq for OnceCell<T>;
impl<T: Eq> Eq for OnceCell<T>;
```
```rust
// std::sync (in std/sync/once_lock.rs)
impl<T> OnceLock<T> {
pub const fn new() -> OnceLock<T>;
pub fn get(&self) -> Option<&T>;
pub fn get_mut(&mut self) -> Option<&mut T>;
pub fn set(&self, value: T) -> Result<(), T>;
pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T;
pub fn into_inner(self) -> Option<T>;
pub fn take(&mut self) -> Option<T>;
}
impl<T: Clone> Clone for OnceLock<T>;
impl<T: Debug> Debug for OnceLock<T>;
impl<T> Default for OnceLock<T>;
impl<#[may_dangle] T> Drop for OnceLock<T>;
impl<T> From<T> for OnceLock<T>;
impl<T: PartialEq> PartialEq for OnceLock<T>
impl<T: Eq> Eq for OnceLock<T>;
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T>;
unsafe impl<T: Send> Send for OnceLock<T>;
unsafe impl<T: Sync + Send> Sync for OnceLock<T>;
impl<T: UnwindSafe> UnwindSafe for OnceLock<T>;
```
No longer planned as part of this PR, and moved to the `rust_cell_try` feature gate:
```rust
impl<T> OnceCell<T> {
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>;
}
impl<T> OnceLock<T> {
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>;
}
```
I am new to this process so would appreciate mentorship wherever needed.
Remove ~const from alloc
There is currently an effort underway to stop using `~const Trait`, temporarily, so as to refactor the logic underlying const traits with relative ease. This means it has to go from the standard library, as well.
I have taken the initial step of just removing these impls from alloc, as removing them from core is a much more tangled task. In addition, all of these implementations are one more-or-less logically-connected group, so reverting their deconstification as a group seems like it will also be sensible.
r? `@fee1-dead`
Change advance(_back)_by to return the remainder instead of the number of processed elements
When advance_by can't advance the iterator by the number of requested elements it now returns the amount by which it couldn't be advanced instead of the amount by which it did.
This simplifies adapters like chain, flatten or cycle because the remainder doesn't have to be calculated as the difference between requested steps and completed steps anymore.
Additionally switching from `Result<(), usize>` to `Result<(), NonZeroUsize>` reduces the size of the result and makes converting from/to a usize representing the number of remaining steps cheap.
A successful advance is now signalled by returning `0` and other values now represent the remaining number
of steps that couldn't be advanced as opposed to the amount of steps that have been advanced during a partial advance_by.
This simplifies adapters a bit, replacing some `match`/`if` with arithmetic. Whether this is beneficial overall depends
on whether `advance_by` is mostly used as a building-block for other iterator methods and adapters or whether
we also see uses by users where `Result` might be more useful.
Stabilize `nonnull_slice_from_raw_parts`
FCP is done: https://github.com/rust-lang/rust/issues/71941#issuecomment-1100910416
Note that this doesn't const-stabilize `NonNull::slice_from_raw_parts` as `slice_from_raw_parts_mut` isn't const-stabilized yet. Given #67456 and #57349, it's not likely available soon, meanwhile, stabilizing only the feature makes some sense, I think.
Closes#71941
Update VecDeque implementation to use head+len instead of head+tail
(See #99805)
This changes `alloc::collections::VecDeque`'s internal representation from using head and tail indices to using a head index and a length field. It has a few advantages over the current design:
* It allows the buffer to be of length 0, which means the `VecDeque::new` new longer has to allocate and could be changed to a `const fn`
* It allows the `VecDeque` to fill the buffer completely, unlike the old implementation, which always had to leave a free space
* It removes the restriction for the size to be a power of two, allowing it to properly `shrink_to_fit`, unlike the old `VecDeque`
* The above points also combine to allow the `Vec<T> -> VecDeque<T>` conversion to be very cheap and guaranteed O(1). I mention this in the `From<Vec<T>>` impl, but it's not a strong guarantee just yet, as that would likely need some form of API change proposal.
All the tests seem to pass for the new `VecDeque`, with some slight adjustments.
r? `@scottmcm`
`VecDeque::resize` should re-use the buffer in the passed-in element
Today it always copies it for *every* appended element, but one of those clones is avoidable.
This adds `iter::repeat_n` (https://github.com/rust-lang/rust/issues/104434) as the primitive needed to do this. If this PR is acceptable, I'll also use this in `Vec` rather than its custom `ExtendElement` type & infrastructure that is harder to share between multiple different containers:
101e1822c3/library/alloc/src/vec/mod.rs (L2479-L2492)
Attempt to reuse `Vec<T>` backing storage for `Rc/Arc<[T]>`
If a `Vec<T>` has sufficient capacity to store the inner `RcBox<[T]>`, we can just reuse the existing allocation and shift the elements up, instead of making a new allocation.
Previously "bare\r" was split into ["bare"] even though the
documentation said that only LF and CRLF count as newlines.
This fix is a behavioural change, even though it brings the behaviour
into line with the documentation, and into line with that of
`std::io::BufRead::lines()`.
This is an alternative to #91051, which proposes to document rather
than fix the behaviour.
Fixes#94435.
Co-authored-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Currently pretty much all of the btree_map and btree_set ones fail, as
well as linked_list::DrainFilter.
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:38:5
|
38 | / require_send_sync(async {
39 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
40 | | async {}.await;
41 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:56:5
|
56 | / require_send_sync(async {
57 | | let _v = None::<
58 | | alloc::collections::btree_map::DrainFilter<
59 | | '_,
... |
65 | | async {}.await;
66 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:68:5
|
68 | / require_send_sync(async {
69 | | let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>;
70 | | async {}.await;
71 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:88:5
|
88 | / require_send_sync(async {
89 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
90 | | async {}.await;
91 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:93:5
|
93 | / require_send_sync(async {
94 | | let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>;
95 | | async {}.await;
96 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:98:5
|
98 | / require_send_sync(async {
99 | | let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>;
100 | | async {}.await;
101 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:103:5
|
103 | / require_send_sync(async {
104 | | let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>;
105 | | async {}.await;
106 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:108:5
|
108 | / require_send_sync(async {
109 | | let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>;
110 | | async {}.await;
111 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:113:5
|
113 | / require_send_sync(async {
114 | | let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>;
115 | | async {}.await;
116 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:118:5
|
118 | / require_send_sync(async {
119 | | let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>;
120 | | async {}.await;
121 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:123:5
|
123 | / require_send_sync(async {
124 | | let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>;
125 | | async {}.await;
126 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:128:5
|
128 | / require_send_sync(async {
129 | | let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>;
130 | | async {}.await;
131 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:133:5
|
133 | / require_send_sync(async {
134 | | let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>;
135 | | async {}.await;
136 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:146:5
|
146 | / require_send_sync(async {
147 | | let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>;
148 | | async {}.await;
149 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: implementation of `Send` is not general enough
--> library/alloc/tests/autotraits.rs:151:5
|
151 | / require_send_sync(async {
152 | | let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>;
153 | | async {}.await;
154 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:156:5
|
156 | / require_send_sync(async {
157 | | let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>;
158 | | async {}.await;
159 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:166:5
|
166 | / require_send_sync(async {
167 | | let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>;
168 | | async {}.await;
169 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:171:5
|
171 | / require_send_sync(async {
172 | | let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>;
173 | | async {}.await;
174 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:176:5
|
176 | / require_send_sync(async {
177 | | let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>;
178 | | async {}.await;
179 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: higher-ranked lifetime error
--> library/alloc/tests/autotraits.rs:181:5
|
181 | / require_send_sync(async {
182 | | let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>;
183 | | async {}.await;
184 | | });
| |______^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: future cannot be sent between threads safely
--> library/alloc/tests/autotraits.rs:243:23
|
243 | require_send_sync(async {
| _______________________^
244 | | let _v =
245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
246 | | async {}.await;
247 | | });
| |_____^ future created by async block is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>`
note: future is not `Send` as this value is used across an await
--> library/alloc/tests/autotraits.rs:246:17
|
244 | let _v =
| -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Send`
245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
246 | async {}.await;
| ^^^^^^ await occurs here, with `_v` maybe used later
247 | });
| - `_v` is later dropped here
note: required by a bound in `require_send_sync`
--> library/alloc/tests/autotraits.rs:3:25
|
3 | fn require_send_sync<T: Send + Sync>(_: T) {}
| ^^^^ required by this bound in `require_send_sync`
error: future cannot be shared between threads safely
--> library/alloc/tests/autotraits.rs:243:23
|
243 | require_send_sync(async {
| _______________________^
244 | | let _v =
245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
246 | | async {}.await;
247 | | });
| |_____^ future created by async block is not `Sync`
|
= help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>`
note: future is not `Sync` as this value is used across an await
--> library/alloc/tests/autotraits.rs:246:17
|
244 | let _v =
| -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Sync`
245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
246 | async {}.await;
| ^^^^^^ await occurs here, with `_v` maybe used later
247 | });
| - `_v` is later dropped here
note: required by a bound in `require_send_sync`
--> library/alloc/tests/autotraits.rs:3:32
|
3 | fn require_send_sync<T: Send + Sync>(_: T) {}
| ^^^^ required by this bound in `require_send_sync`
Fix in-place collection leak when remaining element destructor panic
Fixes#101628
cc `@the8472`
I went for the drop guard route, placing it immediately before the `forget_allocation_drop_remaining` call and after the comment, as to signal they are closely related.
I also updated the test to check for the leak, though the only change really needed was removing the leak clean up for miri since now that's no longer leaked.
Stabilize bench_black_box
This PR stabilize `feature(bench_black_box)`.
```rust
pub fn black_box<T>(dummy: T) -> T;
```
The FCP was completed in https://github.com/rust-lang/rust/issues/64102.
`@rustbot` label +T-libs-api -T-libs
Since `len` and `is_empty` are not const stable yet, this also
creates a new feature for them since they previously used the same
`const_btree_new` feature.
Add `vec::Drain{,Filter}::keep_rest`
This PR adds `keep_rest` methods to `vec::Drain` and `vec::DrainFilter` under `drain_keep_rest` feature gate:
```rust
// mod alloc::vec
impl<T, A: Allocator> Drain<'_, T, A> {
pub fn keep_rest(self);
}
impl<T, F, A: Allocator> DrainFilter<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,
{
pub fn keep_rest(self);
}
```
Both these methods cancel draining of elements that were not yet yielded from the iterators. While this needs more testing & documentation, I want at least start the discussion. This may be a potential way out of the "should `DrainFilter` exhaust itself on drop?" argument.
Use pointer `is_aligned*` methods
This PR replaces some manual alignment checks with calls to `pointer::{is_aligned, is_aligned_to}` and removes a useless pointer cast.
r? `@scottmcm`
_split off from #100746_
Add tests that check `Vec::retain` predicate execution order.
This behaviour is documented for `Vec::retain` which means that there is code that rely on that but there weren't tests about that.