Skip to content

Commit bf493f5

Browse files
committed
Auto merge of rust-lang#126557 - GrigorenkoPV:vec_track_caller, r=<try>
Add `#[track_caller]` to allocating methods of `Vec` & `VecDeque` Part 4 in a lengthy saga. r? `@joshtriplett` because they were the reviewer the last 3 times. `@bors` rollup=never "[just in case this has perf effects, Vec is hot](rust-lang#79323 (comment))" This was first attempted in rust-lang#79323 by `@nvzqz.` It got approval from `@joshtriplett,` but rotted with merge conflicts and got closed. Then it got picked up by `@Dylan-DPC-zz` in rust-lang#83359. A benchmark was run[^perf], the results (after a bit of thinking[^thinking]) were deemed ok[^ok], but there was a typo[^typo] and the PR was made from a wrong remote in the first place[^remote], so rust-lang#83909 was opened instead. By the time rust-lang#83909 rolled around, the methods in question had received some optimizations[^optimizations], so another perf run was conducted[^perf2]. The results were ok[^ok2]. There was a suggestion to add regression tests for panic behavior [^tests], but before it could be addressed, the PR fell victim to merge conflicts[^conflicts] and died again[^rip]. 3 years have passed, and (from what I can tell) this has not been tried again, so here I am now, reviving this old effort. Given how much time has passed and the fact that I've also touched `VecDeque` this time, it probably makes sense to `@bors` try `@rust-timer` [^perf]: rust-lang#83359 (comment) [^thinking]: rust-lang#83359 (comment) [^ok]: rust-lang#83359 (comment) [^typo]: rust-lang#83359 (comment) [^remote]: rust-lang#83359 (comment) [^optimizations]: rust-lang#83909 (comment) [^perf2]: rust-lang#83909 (comment) [^ok2]: rust-lang#83909 (comment) [^tests]: rust-lang#83909 (comment) [^conflicts]: rust-lang#83909 (comment) [^rip]: rust-lang#83909 (comment)
2 parents 59a74db + 90d80a9 commit bf493f5

14 files changed

+108
-3
lines changed

library/alloc/src/collections/vec_deque/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub struct VecDeque<
103103

104104
#[stable(feature = "rust1", since = "1.0.0")]
105105
impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
106+
#[track_caller]
106107
fn clone(&self) -> Self {
107108
let mut deq = Self::with_capacity_in(self.len(), self.allocator().clone());
108109
deq.extend(self.iter().cloned());
@@ -113,6 +114,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
113114
///
114115
/// This method is preferred over simply assigning `source.clone()` to `self`,
115116
/// as it avoids reallocation if possible.
117+
#[track_caller]
116118
fn clone_from(&mut self, source: &Self) {
117119
self.clear();
118120
self.extend(source.iter().cloned());
@@ -490,6 +492,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
490492
/// Frobs the head and tail sections around to handle the fact that we
491493
/// just reallocated. Unsafe because it trusts old_capacity.
492494
#[inline]
495+
#[track_caller]
493496
unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) {
494497
let new_capacity = self.capacity();
495498
debug_assert!(new_capacity >= old_capacity);
@@ -570,6 +573,7 @@ impl<T> VecDeque<T> {
570573
#[inline]
571574
#[stable(feature = "rust1", since = "1.0.0")]
572575
#[must_use]
576+
#[track_caller]
573577
pub fn with_capacity(capacity: usize) -> VecDeque<T> {
574578
Self::with_capacity_in(capacity, Global)
575579
}
@@ -625,6 +629,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
625629
/// let deque: VecDeque<u32> = VecDeque::with_capacity(10);
626630
/// ```
627631
#[unstable(feature = "allocator_api", issue = "32838")]
632+
#[track_caller]
628633
pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
629634
VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) }
630635
}
@@ -789,6 +794,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
789794
///
790795
/// [`reserve`]: VecDeque::reserve
791796
#[stable(feature = "rust1", since = "1.0.0")]
797+
#[track_caller]
792798
pub fn reserve_exact(&mut self, additional: usize) {
793799
let new_cap = self.len.checked_add(additional).expect("capacity overflow");
794800
let old_cap = self.capacity();
@@ -818,6 +824,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
818824
/// assert!(buf.capacity() >= 11);
819825
/// ```
820826
#[stable(feature = "rust1", since = "1.0.0")]
827+
#[track_caller]
821828
pub fn reserve(&mut self, additional: usize) {
822829
let new_cap = self.len.checked_add(additional).expect("capacity overflow");
823830
let old_cap = self.capacity();
@@ -949,6 +956,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
949956
/// assert!(buf.capacity() >= 4);
950957
/// ```
951958
#[stable(feature = "deque_extras_15", since = "1.5.0")]
959+
#[track_caller]
952960
pub fn shrink_to_fit(&mut self) {
953961
self.shrink_to(0);
954962
}
@@ -974,6 +982,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
974982
/// assert!(buf.capacity() >= 4);
975983
/// ```
976984
#[stable(feature = "shrink_to", since = "1.56.0")]
985+
#[track_caller]
977986
pub fn shrink_to(&mut self, min_capacity: usize) {
978987
let target_cap = min_capacity.max(self.len);
979988

@@ -1739,6 +1748,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
17391748
/// assert_eq!(d.front(), Some(&2));
17401749
/// ```
17411750
#[stable(feature = "rust1", since = "1.0.0")]
1751+
#[track_caller]
17421752
pub fn push_front(&mut self, value: T) {
17431753
if self.is_full() {
17441754
self.grow();
@@ -1766,6 +1776,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
17661776
/// ```
17671777
#[stable(feature = "rust1", since = "1.0.0")]
17681778
#[rustc_confusables("push", "put", "append")]
1779+
#[track_caller]
17691780
pub fn push_back(&mut self, value: T) {
17701781
if self.is_full() {
17711782
self.grow();
@@ -1875,6 +1886,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
18751886
/// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']);
18761887
/// ```
18771888
#[stable(feature = "deque_extras_15", since = "1.5.0")]
1889+
#[track_caller]
18781890
pub fn insert(&mut self, index: usize, value: T) {
18791891
assert!(index <= self.len(), "index out of bounds");
18801892
if self.is_full() {
@@ -1978,6 +1990,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
19781990
#[inline]
19791991
#[must_use = "use `.truncate()` if you don't need the other half"]
19801992
#[stable(feature = "split_off", since = "1.4.0")]
1993+
#[track_caller]
19811994
pub fn split_off(&mut self, at: usize) -> Self
19821995
where
19831996
A: Clone,
@@ -2044,6 +2057,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
20442057
/// ```
20452058
#[inline]
20462059
#[stable(feature = "append", since = "1.4.0")]
2060+
#[track_caller]
20472061
pub fn append(&mut self, other: &mut Self) {
20482062
if T::IS_ZST {
20492063
self.len = self.len.checked_add(other.len).expect("capacity overflow");
@@ -2166,6 +2180,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
21662180
// be called in cold paths.
21672181
// This may panic or abort
21682182
#[inline(never)]
2183+
#[track_caller]
21692184
fn grow(&mut self) {
21702185
// Extend or possibly remove this assertion when valid use-cases for growing the
21712186
// buffer without it being full emerge
@@ -2204,6 +2219,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
22042219
/// assert_eq!(buf, [5, 10, 101, 102, 103]);
22052220
/// ```
22062221
#[stable(feature = "vec_resize_with", since = "1.33.0")]
2222+
#[track_caller]
22072223
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) {
22082224
let len = self.len;
22092225

@@ -2750,6 +2766,7 @@ impl<T: Clone, A: Allocator> VecDeque<T, A> {
27502766
/// assert_eq!(buf, [5, 10, 20, 20, 20]);
27512767
/// ```
27522768
#[stable(feature = "deque_extras", since = "1.16.0")]
2769+
#[track_caller]
27532770
pub fn resize(&mut self, new_len: usize, value: T) {
27542771
if new_len > self.len() {
27552772
let extra = new_len - self.len();
@@ -2869,6 +2886,7 @@ impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
28692886

28702887
#[stable(feature = "rust1", since = "1.0.0")]
28712888
impl<T> FromIterator<T> for VecDeque<T> {
2889+
#[track_caller]
28722890
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
28732891
SpecFromIter::spec_from_iter(iter.into_iter())
28742892
}
@@ -2908,16 +2926,19 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque<T, A> {
29082926

29092927
#[stable(feature = "rust1", since = "1.0.0")]
29102928
impl<T, A: Allocator> Extend<T> for VecDeque<T, A> {
2929+
#[track_caller]
29112930
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
29122931
<Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter());
29132932
}
29142933

29152934
#[inline]
2935+
#[track_caller]
29162936
fn extend_one(&mut self, elem: T) {
29172937
self.push_back(elem);
29182938
}
29192939

29202940
#[inline]
2941+
#[track_caller]
29212942
fn extend_reserve(&mut self, additional: usize) {
29222943
self.reserve(additional);
29232944
}
@@ -2933,16 +2954,19 @@ impl<T, A: Allocator> Extend<T> for VecDeque<T, A> {
29332954

29342955
#[stable(feature = "extend_ref", since = "1.2.0")]
29352956
impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> {
2957+
#[track_caller]
29362958
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
29372959
self.spec_extend(iter.into_iter());
29382960
}
29392961

29402962
#[inline]
2963+
#[track_caller]
29412964
fn extend_one(&mut self, &elem: &'a T) {
29422965
self.push_back(elem);
29432966
}
29442967

29452968
#[inline]
2969+
#[track_caller]
29462970
fn extend_reserve(&mut self, additional: usize) {
29472971
self.reserve(additional);
29482972
}
@@ -3040,6 +3064,7 @@ impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
30403064
/// let deq2: VecDeque<_> = [1, 2, 3, 4].into();
30413065
/// assert_eq!(deq1, deq2);
30423066
/// ```
3067+
#[track_caller]
30433068
fn from(arr: [T; N]) -> Self {
30443069
let mut deq = VecDeque::with_capacity(N);
30453070
let arr = ManuallyDrop::new(arr);

library/alloc/src/collections/vec_deque/spec_extend.rs

+6
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use crate::vec;
77

88
// Specialization trait used for VecDeque::extend
99
pub(super) trait SpecExtend<T, I> {
10+
#[track_caller]
1011
fn spec_extend(&mut self, iter: I);
1112
}
1213

1314
impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
1415
where
1516
I: Iterator<Item = T>,
1617
{
18+
#[track_caller]
1719
default fn spec_extend(&mut self, mut iter: I) {
1820
// This function should be the moral equivalent of:
1921
//
@@ -44,6 +46,7 @@ impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
4446
where
4547
I: TrustedLen<Item = T>,
4648
{
49+
#[track_caller]
4750
default fn spec_extend(&mut self, iter: I) {
4851
// This is the case for a TrustedLen iterator.
4952
let (low, high) = iter.size_hint();
@@ -76,6 +79,7 @@ where
7679
}
7780

7881
impl<T, A: Allocator> SpecExtend<T, vec::IntoIter<T>> for VecDeque<T, A> {
82+
#[track_caller]
7983
fn spec_extend(&mut self, mut iterator: vec::IntoIter<T>) {
8084
let slice = iterator.as_slice();
8185
self.reserve(slice.len());
@@ -93,6 +97,7 @@ where
9397
I: Iterator<Item = &'a T>,
9498
T: Copy,
9599
{
100+
#[track_caller]
96101
default fn spec_extend(&mut self, iterator: I) {
97102
self.spec_extend(iterator.copied())
98103
}
@@ -102,6 +107,7 @@ impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque
102107
where
103108
T: Copy,
104109
{
110+
#[track_caller]
105111
fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
106112
let slice = iterator.as_slice();
107113
self.reserve(slice.len());

library/alloc/src/collections/vec_deque/spec_from_iter.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ impl<T, I> SpecFromIter<T, I> for VecDeque<T>
99
where
1010
I: Iterator<Item = T>,
1111
{
12+
#[track_caller]
1213
default fn spec_from_iter(iterator: I) -> Self {
1314
// Since converting is O(1) now, just re-use the `Vec` logic for
1415
// anything where we can't do something extra-special for `VecDeque`,

library/alloc/src/raw_vec.rs

+17
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mod tests;
2020
// only one location which panics rather than a bunch throughout the module.
2121
#[cfg(not(no_global_oom_handling))]
2222
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
23+
#[track_caller]
2324
fn capacity_overflow() -> ! {
2425
panic!("capacity overflow");
2526
}
@@ -132,6 +133,7 @@ impl<T> RawVec<T, Global> {
132133
#[cfg(not(any(no_global_oom_handling, test)))]
133134
#[must_use]
134135
#[inline]
136+
#[track_caller]
135137
pub fn with_capacity(capacity: usize) -> Self {
136138
Self { inner: RawVecInner::with_capacity(capacity, T::LAYOUT), _marker: PhantomData }
137139
}
@@ -140,6 +142,7 @@ impl<T> RawVec<T, Global> {
140142
#[cfg(not(any(no_global_oom_handling, test)))]
141143
#[must_use]
142144
#[inline]
145+
#[track_caller]
143146
pub fn with_capacity_zeroed(capacity: usize) -> Self {
144147
Self {
145148
inner: RawVecInner::with_capacity_zeroed_in(capacity, Global, T::LAYOUT),
@@ -158,6 +161,7 @@ impl RawVecInner<Global> {
158161
#[cfg(not(any(no_global_oom_handling, test)))]
159162
#[must_use]
160163
#[inline]
164+
#[track_caller]
161165
fn with_capacity(capacity: usize, elem_layout: Layout) -> Self {
162166
match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global, elem_layout) {
163167
Ok(res) => res,
@@ -197,6 +201,7 @@ impl<T, A: Allocator> RawVec<T, A> {
197201
/// allocator for the returned `RawVec`.
198202
#[cfg(not(no_global_oom_handling))]
199203
#[inline]
204+
#[track_caller]
200205
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
201206
Self {
202207
inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT),
@@ -218,6 +223,7 @@ impl<T, A: Allocator> RawVec<T, A> {
218223
/// of allocator for the returned `RawVec`.
219224
#[cfg(not(no_global_oom_handling))]
220225
#[inline]
226+
#[track_caller]
221227
pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
222228
Self {
223229
inner: RawVecInner::with_capacity_zeroed_in(capacity, alloc, T::LAYOUT),
@@ -337,6 +343,7 @@ impl<T, A: Allocator> RawVec<T, A> {
337343
/// Aborts on OOM.
338344
#[cfg(not(no_global_oom_handling))]
339345
#[inline]
346+
#[track_caller]
340347
pub fn reserve(&mut self, len: usize, additional: usize) {
341348
self.inner.reserve(len, additional, T::LAYOUT)
342349
}
@@ -345,6 +352,7 @@ impl<T, A: Allocator> RawVec<T, A> {
345352
/// caller to ensure `len == self.capacity()`.
346353
#[cfg(not(no_global_oom_handling))]
347354
#[inline(never)]
355+
#[track_caller]
348356
pub fn grow_one(&mut self) {
349357
self.inner.grow_one(T::LAYOUT)
350358
}
@@ -372,6 +380,7 @@ impl<T, A: Allocator> RawVec<T, A> {
372380
///
373381
/// Aborts on OOM.
374382
#[cfg(not(no_global_oom_handling))]
383+
#[track_caller]
375384
pub fn reserve_exact(&mut self, len: usize, additional: usize) {
376385
self.inner.reserve_exact(len, additional, T::LAYOUT)
377386
}
@@ -396,6 +405,7 @@ impl<T, A: Allocator> RawVec<T, A> {
396405
///
397406
/// Aborts on OOM.
398407
#[cfg(not(no_global_oom_handling))]
408+
#[track_caller]
399409
#[inline]
400410
pub fn shrink_to_fit(&mut self, cap: usize) {
401411
self.inner.shrink_to_fit(cap, T::LAYOUT)
@@ -421,6 +431,7 @@ impl<A: Allocator> RawVecInner<A> {
421431

422432
#[cfg(not(no_global_oom_handling))]
423433
#[inline]
434+
#[track_caller]
424435
fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
425436
match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) {
426437
Ok(this) => {
@@ -445,6 +456,7 @@ impl<A: Allocator> RawVecInner<A> {
445456

446457
#[cfg(not(no_global_oom_handling))]
447458
#[inline]
459+
#[track_caller]
448460
fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
449461
match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) {
450462
Ok(res) => res,
@@ -539,6 +551,7 @@ impl<A: Allocator> RawVecInner<A> {
539551

540552
#[cfg(not(no_global_oom_handling))]
541553
#[inline]
554+
#[track_caller]
542555
fn reserve(&mut self, len: usize, additional: usize, elem_layout: Layout) {
543556
// Callers expect this function to be very cheap when there is already sufficient capacity.
544557
// Therefore, we move all the resizing and error-handling logic from grow_amortized and
@@ -563,6 +576,7 @@ impl<A: Allocator> RawVecInner<A> {
563576

564577
#[cfg(not(no_global_oom_handling))]
565578
#[inline]
579+
#[track_caller]
566580
fn grow_one(&mut self, elem_layout: Layout) {
567581
if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) {
568582
handle_error(err);
@@ -586,6 +600,7 @@ impl<A: Allocator> RawVecInner<A> {
586600
}
587601

588602
#[cfg(not(no_global_oom_handling))]
603+
#[track_caller]
589604
fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) {
590605
if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) {
591606
handle_error(err);
@@ -610,6 +625,7 @@ impl<A: Allocator> RawVecInner<A> {
610625

611626
#[cfg(not(no_global_oom_handling))]
612627
#[inline]
628+
#[track_caller]
613629
fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) {
614630
if let Err(err) = self.shrink(cap, elem_layout) {
615631
handle_error(err);
@@ -782,6 +798,7 @@ where
782798
// Central function for reserve error handling.
783799
#[cfg(not(no_global_oom_handling))]
784800
#[cold]
801+
#[track_caller]
785802
fn handle_error(e: TryReserveError) -> ! {
786803
match e.kind() {
787804
CapacityOverflow => capacity_overflow(),

library/alloc/src/vec/cow.rs

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ impl<'a, T> FromIterator<T> for Cow<'a, [T]>
5858
where
5959
T: Clone,
6060
{
61+
#[track_caller]
6162
fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
6263
Cow::Owned(FromIterator::from_iter(it))
6364
}

0 commit comments

Comments
 (0)