Skip to content

Commit 6d93ce3

Browse files
authored
Merge pull request #61 from zachs18/drain-variance
Make `Drain<'_, T>` covariant in `T`.
2 parents 85ae2ea + e853887 commit 6d93ce3

File tree

1 file changed

+22
-28
lines changed

1 file changed

+22
-28
lines changed

src/lib.rs

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ use core::marker::PhantomData;
158158
use core::ops::Bound;
159159
use core::ops::{Deref, DerefMut, RangeBounds};
160160
use core::ptr::NonNull;
161-
use core::slice::IterMut;
161+
use core::slice::Iter;
162162
use core::{fmt, mem, ptr, slice};
163163

164164
use impl_details::*;
@@ -1477,12 +1477,11 @@ impl<T> ThinVec<T> {
14771477
// Set our length to the start bound
14781478
self.set_len(start); // could be the singleton
14791479

1480-
let iter =
1481-
slice::from_raw_parts_mut(self.data_raw().add(start), end - start).iter_mut();
1480+
let iter = slice::from_raw_parts(self.data_raw().add(start), end - start).iter();
14821481

14831482
Drain {
14841483
iter,
1485-
vec: self,
1484+
vec: NonNull::from(self),
14861485
end,
14871486
tail: len - end,
14881487
}
@@ -2442,20 +2441,17 @@ pub struct Drain<'a, T> {
24422441
// and setting `len` to `len + tail_len` to undo the leak amplification.
24432442
/// An iterator over the elements we're removing.
24442443
///
2445-
/// As we go we'll be `read`ing out of the mutable refs yielded by this.
2446-
/// It's ok to use IterMut here because it promises to only take mutable
2447-
/// refs to the parts we haven't yielded yet.
2448-
///
2449-
/// A downside of this (and the *mut below) is that it makes this type invariant, when
2450-
/// technically it could be covariant?
2451-
iter: IterMut<'a, T>,
2444+
/// As we go we'll be `read`ing out of the shared refs yielded by this.
2445+
/// It's ok to use Iter here because it promises to only take refs to the parts
2446+
/// we haven't yielded yet.
2447+
iter: Iter<'a, T>,
24522448
/// The actual ThinVec, which we need to hold onto to undo the leak amplification
24532449
/// and backshift the tail into place. This should only be accessed when we're
2454-
/// completely done with the IterMut in the `drop` impl of this type (or miri will get mad).
2450+
/// completely done with the Iter in the `drop` impl of this type (or miri will get mad).
24552451
///
2456-
/// Since we set the `len` of this to be before `IterMut`, we can use that `len`
2452+
/// Since we set the `len` of this to be before `Iter`, we can use that `len`
24572453
/// to retrieve the index of the start of the drain range later.
2458-
vec: *mut ThinVec<T>,
2454+
vec: NonNull<ThinVec<T>>,
24592455
/// The one-past-the-end index of the drain range, or equivalently the start of the tail.
24602456
end: usize,
24612457
/// The length of the tail.
@@ -2494,7 +2490,7 @@ impl<'a, T> Drop for Drain<'a, T> {
24942490

24952491
// Move the tail over the drained items, and update the length.
24962492
unsafe {
2497-
let vec = &mut *self.vec;
2493+
let vec = self.vec.as_mut();
24982494

24992495
// Don't mutate the empty singleton!
25002496
if !vec.is_singleton() {
@@ -2591,7 +2587,7 @@ impl<I: Iterator> Drop for Splice<'_, I> {
25912587
// If there's no tail elements, then the inner ThinVec is already
25922588
// correct and we can just extend it like normal.
25932589
if self.drain.tail == 0 {
2594-
(*self.drain.vec).extend(self.replace_with.by_ref());
2590+
self.drain.vec.as_mut().extend(self.replace_with.by_ref());
25952591
return;
25962592
}
25972593

@@ -2740,7 +2736,7 @@ impl<T> Drain<'_, T> {
27402736
/// Fill that range as much as possible with new elements from the `replace_with` iterator.
27412737
/// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
27422738
unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
2743-
let vec = unsafe { &mut *self.vec };
2739+
let vec = unsafe { self.vec.as_mut() };
27442740
let range_start = vec.len();
27452741
let range_end = self.end;
27462742
let range_slice = unsafe {
@@ -2760,7 +2756,7 @@ impl<T> Drain<'_, T> {
27602756

27612757
/// Makes room for inserting more elements before the tail.
27622758
unsafe fn move_tail(&mut self, additional: usize) {
2763-
let vec = unsafe { &mut *self.vec };
2759+
let vec = unsafe { self.vec.as_mut() };
27642760
let len = self.end + self.tail;
27652761
vec.reserve(len.checked_add(additional).unwrap_cap_overflow());
27662762

@@ -3937,17 +3933,15 @@ mod std_tests {
39373933
assert_eq!(it.next(), None);
39383934
}
39393935

3940-
/* TODO: make drain covariant
3941-
#[allow(dead_code)]
3942-
fn assert_covariance() {
3943-
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
3944-
d
3945-
}
3946-
fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
3947-
i
3948-
}
3936+
#[allow(dead_code)]
3937+
fn assert_covariance() {
3938+
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
3939+
d
39493940
}
3950-
*/
3941+
fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
3942+
i
3943+
}
3944+
}
39513945

39523946
/* TODO: specialize vec.into_iter().collect::<ThinVec<_>>();
39533947
#[test]

0 commit comments

Comments
 (0)