This commit is contained in:
missing 2022-06-08 23:00:11 -05:00
parent d46bdc4a57
commit 192099e60b
7 changed files with 156 additions and 71 deletions

View file

@ -6,3 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
[features]
unstable = []

View file

@ -1,2 +1,5 @@
# dyn_vec # A `Vec<T: ?Sized>`
A dynamic length collection of unsized elements, akin to `std::vec::Vec`.
Check the crate-level documentation for more info.

View file

@ -63,6 +63,17 @@ impl<T: PartialEq<U>, U, const N: usize> PartialEq<Vec<T>> for [U; N] {
} }
} }
#[cfg(not(feature = "unstable"))]
impl<T: ?Sized> Extend<Box<T>> for Vec<T> {
fn extend<I: IntoIterator<Item = Box<T>>>(&mut self, iter: I) {
for item in iter {
// TODO: optmize
self.push_box(item);
}
}
}
#[cfg(feature = "unstable")]
impl<T: ?Sized, U: ?Sized> Extend<Box<U>> for Vec<T> where Box<U>: CoerceUnsized<Box<T>> { impl<T: ?Sized, U: ?Sized> Extend<Box<U>> for Vec<T> where Box<U>: CoerceUnsized<Box<T>> {
fn extend<I: IntoIterator<Item = Box<U>>>(&mut self, iter: I) { fn extend<I: IntoIterator<Item = Box<U>>>(&mut self, iter: I) {
for item in iter { for item in iter {

View file

@ -60,6 +60,9 @@ pub struct Iter<'a, T: ?Sized> {
_phantom: PhantomData<&'a T> _phantom: PhantomData<&'a T>
} }
unsafe impl<'a, T: Send> Send for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
impl<'a, T: ?Sized> Iter<'a, T> { impl<'a, T: ?Sized> Iter<'a, T> {
/// Creates a new by-ref iterator over a [`Vec`]. usually seen as [`Vec::iter`]. /// Creates a new by-ref iterator over a [`Vec`]. usually seen as [`Vec::iter`].
pub fn new(vec: &'a Vec<T>) -> Self { pub fn new(vec: &'a Vec<T>) -> Self {
@ -100,6 +103,9 @@ pub struct IterMut<'a, T: ?Sized> {
_phantom: PhantomData<&'a mut T> _phantom: PhantomData<&'a mut T>
} }
unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
impl<'a, T: ?Sized> IterMut<'a, T> { impl<'a, T: ?Sized> IterMut<'a, T> {
/// Creates a new by-mut iterator over a [`Vec`]. usually seen as [`Vec::iter_mut`]. /// Creates a new by-mut iterator over a [`Vec`]. usually seen as [`Vec::iter_mut`].
pub fn new(vec: &'a mut Vec<T>) -> Self { pub fn new(vec: &'a mut Vec<T>) -> Self {
@ -141,6 +147,9 @@ pub struct IntoIter<T: ?Sized> {
base: BaseIter<T> base: BaseIter<T>
} }
unsafe impl<T: Send> Send for IntoIter<T> {}
unsafe impl<T: Sync> Sync for IntoIter<T> {}
impl<T: ?Sized> IntoIter<T> { impl<T: ?Sized> IntoIter<T> {
/// Creates a new by-value iterator over a [`Vec`]. usually seen as [`Vec::into_iter`]. /// Creates a new by-value iterator over a [`Vec`]. usually seen as [`Vec::into_iter`].
pub fn new(vec: Vec<T>) -> Self { pub fn new(vec: Vec<T>) -> Self {

View file

@ -2,11 +2,14 @@
//! //!
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`]. //! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
//! //!
//! This crate depends on a number of unstable features, namely: //! This crate is currently stable, but lacks some functionality. To enable this functionality, use the `"unstable"` crate feature, which depends on the following nightly features:
//! - `#![feature(ptr_metadata)]`, to allow manipulating the metadata of pointers.
//! - `#![feature(layout_for_ptr)]`, to allow getting the size/alignment of a value with only a pointer to it.
//! - `#![feature(coerce_unsized)]`, to add trait bounds for types which can be unsized to another type. //! - `#![feature(coerce_unsized)]`, to add trait bounds for types which can be unsized to another type.
//! //!
//! and enables the following functionality (note: these links are probably broken):
//! - [`Vec::push_unsize`]
//! - [`Vec::unsize`]
//! - [`Vec::extend_unsize`]
//!
//! # Examples //! # Examples
//! //!
//! You can create a vector with [`Vec::new`]: //! You can create a vector with [`Vec::new`]:
@ -49,7 +52,7 @@
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]"); //! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
//! ``` //! ```
//! //!
//! ...and with [`push_box`] and [`push_unsize`]: //! ...and with [`push_box`] and [`push_unsize`] ([`push_unsize_stable`] without the `"unstable"` feature):
//! //!
//! ``` //! ```
//! # use dyn_vec::prelude::{*, vec}; //! # use dyn_vec::prelude::{*, vec};
@ -59,24 +62,27 @@
//! vec.push_box(Box::new("foo")); //! vec.push_box(Box::new("foo"));
//! vec.push_box(Box::new(true)); //! vec.push_box(Box::new(true));
//! //!
//! vec.push_unsize(2); //! // these closures are only needed for the `_stable` versions
//! vec.push_unsize("bar"); //! vec.push_unsize_stable(2, |v| v as _);
//! vec.push_unsize(false); //! vec.push_unsize_stable("bar", |v| v as _);
//! vec.push_unsize_stable(false, |v| v as _);
//! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#); //! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#);
//! ``` //! ```
//! //!
//! Finally, a vector can be `unsize`d to another vector: //! Finally, a vector can be [`unsize`]d to another vector ([`unsize_stable`] on stable):
//! //!
//! ``` //! ```
//! # use dyn_vec::prelude::{*, vec}; //! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug; //! # use std::fmt::Debug;
//! let vec: Vec<i32> = vec![1, 2, 3]; //! let vec: Vec<i32> = vec![1, 2, 3];
//! // vec.push_unsize("foo"); // not yet... //! // vec.push_unsize_stable("foo", |v| v as _); // not yet...
//! let mut vec: Vec<dyn Debug> = vec.unsize(); //! let mut vec: Vec<dyn Debug> = vec.unsize_stable(|v| v as _);
//! vec.push_unsize("foo"); // now we can! //! vec.push_unsize_stable("foo", |v| v as _); // now we can!
//! # assert_eq!(format!("{:?}", vec), r#"[1, 2, 3, "foo"]"#); //! # assert_eq!(format!("{:?}", vec), r#"[1, 2, 3, "foo"]"#);
//! ``` //! ```
//! //!
//! To use the `_stable` variations, one can generally add the argument `|v| v as _`.
//!
//! # Data Layout //! # Data Layout
//! //!
//! ```text //! ```text
@ -101,12 +107,17 @@
//! ``` //! ```
//! //!
//! [`Vec<T: ?Sized>`]: Vec //! [`Vec<T: ?Sized>`]: Vec
//! [`Vec::push_unsize`]: Vec::push_unsize
//! [`Vec::unsize`]: Vec::unsize
//! [`Vec::extend_unsize`]: Vec::extend_unsize
//! [`push_box`]: Vec::push_box //! [`push_box`]: Vec::push_box
//! [`push_unsize`]: Vec::push_unsize //! [`push_unsize`]: Vec::push_unsize
//! [`push_unsize_stable`]: Vec::push_unsize_stable
//! [`unsize`]: Vec::unsize
//! [`unsize_stable`]: Vec::unsize_stable
#![feature(ptr_metadata)] #![cfg_attr(feature = "unstable", feature(coerce_unsized))]
#![feature(layout_for_ptr)] #![feature(backtrace)] // for debugging, REMOVE IT BEFORE COMMIT
#![feature(coerce_unsized)]
// for `mod bad_things`, still a wip // for `mod bad_things`, still a wip
// #![allow(incomplete_features)] // #![allow(incomplete_features)]
// #![feature(specialization)] // #![feature(specialization)]
@ -131,12 +142,17 @@ use std::{
ptr::{NonNull, drop_in_place}, ptr::{NonNull, drop_in_place},
marker::PhantomData, marker::PhantomData,
alloc::{Layout, alloc, dealloc}, alloc::{Layout, alloc, dealloc},
mem::{self, size_of, size_of_val, align_of_val, size_of_val_raw, align_of_val_raw}, mem::{self, size_of, size_of_val, align_of_val},
slice, slice,
ops::{CoerceUnsized, Index, IndexMut}, ops::{Index, IndexMut},
any::Any any::Any
}; };
#[cfg(feature = "unstable")]
use std::ops::CoerceUnsized;
type Coercer<T, U> = for<'a> fn(&'a T) -> &'a U;
mod ptr_ext; mod ptr_ext;
#[allow(clippy::wildcard_imports)] #[allow(clippy::wildcard_imports)]
use ptr_ext::*; use ptr_ext::*;
@ -218,21 +234,31 @@ impl<T: ?Sized> Vec<T> {
pub fn push_box(&mut self, v: Box<T>) { pub fn push_box(&mut self, v: Box<T>) {
let ptr = Box::into_raw(v); let ptr = Box::into_raw(v);
unsafe { unsafe {
let layout = Layout::for_value(&*ptr); // ref it *before* its logically uninit
self.push_raw(ptr); self.push_raw(ptr);
dealloc(ptr.cast(), Layout::for_value_raw(ptr)); dealloc(ptr.cast(), layout);
} }
} }
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`. /// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`.
#[cfg(feature = "unstable")]
pub fn push_unsize<U>(&mut self, v: U) where for<'a> &'a U: CoerceUnsized<&'a T> { pub fn push_unsize<U>(&mut self, v: U) where for<'a> &'a U: CoerceUnsized<&'a T> {
let v_unsized: &T = &v; // TODO: maybe make this not call the stable version for perf?
self.push_unsize_stable(v, |v| v as _);
}
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn push_unsize_stable<U>(&mut self, v: U, coercer: Coercer<U, T>) {
let v_unsized: &T = coercer(&v);
unsafe { self.push_raw(v_unsized) }; unsafe { self.push_raw(v_unsized) };
mem::forget(v); mem::forget(v);
} }
unsafe fn push_raw(&mut self, v: *const T) { unsafe fn push_raw(&mut self, v: *const T) {
if !self.will_fit(&*v) { if !self.will_fit(&*v) {
let new_alloc_size = self.capacity * 2 + size_of_val_raw(v) * 2 + size_of::<Extra<T>>(); let new_alloc_size = self.capacity * 2 + size_of_val(&*v) * 2 + size_of::<Extra<T>>();
self.realloc(new_alloc_size); self.realloc(new_alloc_size);
} }
@ -290,10 +316,10 @@ impl<T: ?Sized> Vec<T> {
for i in 0..self.len { for i in 0..self.len {
let v = self.get_ptr(i); let v = self.get_ptr(i);
ptr = ptr.align_up(align_of_val_raw(v)); ptr = ptr.align_up(align_of_val(&*v));
v.copy_val_to(ptr); v.copy_val_to(ptr);
self.set_extra_from_ptr(i, ptr.with_meta_from(v)); self.set_extra_from_ptr(i, ptr.with_meta_from(v));
ptr = ptr.wrapping_add(size_of_val_raw(v)); ptr = ptr.wrapping_add(size_of_val(&*v));
} }
self.end_ptr = NonNull::new_unchecked(ptr); self.end_ptr = NonNull::new_unchecked(ptr);
@ -415,7 +441,16 @@ impl<T: ?Sized> Vec<T> {
} }
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`. /// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
pub fn unsize<U: ?Sized>(mut self) -> Vec<U> where for<'a> &'a T: CoerceUnsized<&'a U> { #[cfg(feature = "unstable")]
pub fn unsize<U: ?Sized>(self) -> Vec<U> where for<'a> &'a T: CoerceUnsized<&'a U> {
// TODO: maybe make this not call the stable version for perf?
self.unsize_stable(|v| v as _)
}
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn unsize_stable<U: ?Sized>(mut self, coercer: Coercer<T, U>) -> Vec<U> {
if size_of::<Extra<U>>() > size_of::<Extra<T>>() { if size_of::<Extra<U>>() > size_of::<Extra<T>>() {
let elem_size = self.end_ptr.as_ptr().addr() - self.ptr.as_ptr().addr(); let elem_size = self.end_ptr.as_ptr().addr() - self.ptr.as_ptr().addr();
let extra_size = self.len * size_of::<Extra<U>>(); let extra_size = self.len * size_of::<Extra<U>>();
@ -439,7 +474,7 @@ impl<T: ?Sized> Vec<T> {
for i in (0..self.len).rev() { for i in (0..self.len).rev() {
// using references here is necessary for unsizing coercion to work // using references here is necessary for unsizing coercion to work
let current = unsafe { &*self.get_ptr(i) }; let current = unsafe { &*self.get_ptr(i) };
unsafe { new_vec.set_extra_from_ptr(i, current as &U) } unsafe { new_vec.set_extra_from_ptr(i, coercer(current)) }
} }
} else { } else {
// new extra smaller or same size as old extra, must go from front to back // new extra smaller or same size as old extra, must go from front to back
@ -447,7 +482,7 @@ impl<T: ?Sized> Vec<T> {
for i in 0..self.len { for i in 0..self.len {
// using references here is necessary for unsizing coercion to work // using references here is necessary for unsizing coercion to work
let current = unsafe { &*self.get_ptr(i) }; let current = unsafe { &*self.get_ptr(i) };
unsafe { new_vec.set_extra_from_ptr(i, current as &U) } unsafe { new_vec.set_extra_from_ptr(i, coercer(current)) }
} }
} }
@ -464,9 +499,20 @@ impl<T: ?Sized> Vec<T> {
/// Extends this vector with an iterator. /// Extends this vector with an iterator.
/// ///
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations. /// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
#[cfg(feature = "unstable")]
pub fn extend_unsize<U, I: IntoIterator<Item = U>>(&mut self, iter: I) where for<'a> &'a U: CoerceUnsized<&'a T> { pub fn extend_unsize<U, I: IntoIterator<Item = U>>(&mut self, iter: I) where for<'a> &'a U: CoerceUnsized<&'a T> {
// TODO: maybe make this not call the stable version for perf?
self.extend_unsize_stable(iter, |v| v as _);
}
/// Extends this vector with an iterator.
///
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn extend_unsize_stable<U, I: IntoIterator<Item = U>>(&mut self, iter: I, coercer: Coercer<U, T>) {
for item in iter { for item in iter {
self.push_unsize(item); self.push_unsize_stable(item, coercer);
} }
} }
@ -489,7 +535,7 @@ impl<T: ?Sized> Vec<T> {
let mut new_ptr = self.get_ptr_before_pad(index); let mut new_ptr = self.get_ptr_before_pad(index);
// align it up to the align of the NEXT element // align it up to the align of the NEXT element
let next_ptr = self.get_ptr(index + 1); let next_ptr = self.get_ptr(index + 1);
new_ptr = new_ptr.align_up(align_of_val_raw(next_ptr)); new_ptr = new_ptr.align_up(align_of_val(&*next_ptr));
// if its the same, we can break as the rest will be useless // if its the same, we can break as the rest will be useless
if new_ptr == next_ptr { break } if new_ptr == next_ptr { break }
@ -581,9 +627,10 @@ impl Vec<dyn Any> {
impl<T: ?Sized> Drop for Vec<T> { impl<T: ?Sized> Drop for Vec<T> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
for i in 0..self.len { for el in self.iter_mut() {
drop_in_place(self.get_unchecked_mut(i)); drop_in_place(el);
} }
self.dealloc(); self.dealloc();
} }
} }
@ -639,7 +686,8 @@ macro_rules! vec {
}}; }};
(unsized: $($elem:expr),+ $(,)?) => {{ (unsized: $($elem:expr),+ $(,)?) => {{
let mut vec = $crate::Vec::new(); let mut vec = $crate::Vec::new();
$(vec.push_unsize($elem);)+ // TODO: when stuff stabalizes change this
$(vec.push_unsize_stable($elem, |v| v as _);)+
vec vec
}}; }};
($elem:expr; $n:expr) => { ($elem:expr; $n:expr) => {

View file

@ -1,4 +1,4 @@
use std::{ptr::{self, Pointee}, mem::size_of_val_raw, alloc::{alloc, Layout}}; use std::{alloc::{alloc, Layout}, mem::size_of_val, ptr::addr_of_mut};
use self::__priv::Sealed; use self::__priv::Sealed;
@ -37,7 +37,7 @@ impl<T: ?Sized> PtrExt for *const T {
type Pointee = T; type Pointee = T;
fn addr(self) -> usize { fn addr(self) -> usize {
self.to_raw_parts().0 as usize self.data_ptr() as usize
} }
fn align_up(self, align: usize) -> Self { fn align_up(self, align: usize) -> Self {
@ -48,12 +48,15 @@ impl<T: ?Sized> PtrExt for *const T {
self.with_addr(addr.addr()) self.with_addr(addr.addr())
} }
fn with_addr(self, addr: usize) -> Self { fn with_addr(mut self, addr: usize) -> Self {
ptr::from_raw_parts(addr as _, self.to_raw_parts().1) // TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
unsafe { *addr_of_mut!(self).cast() = addr }
self
} }
unsafe fn get_end(self) -> Self { unsafe fn get_end(self) -> Self {
self.add_bytes(size_of_val_raw(self)) // TODO: _raw
self.add_bytes(size_of_val(&*self))
} }
fn add_bytes(self, offset: usize) -> Self { fn add_bytes(self, offset: usize) -> Self {
@ -69,11 +72,13 @@ impl<T: ?Sized> PtrExt for *const T {
} }
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) { unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
self.copy_bytes_to(dest, size_of_val_raw(self)); // TODO: _raw
self.copy_bytes_to(dest, size_of_val(&*self));
} }
unsafe fn read_to_box(self) -> Box<Self::Pointee> { unsafe fn read_to_box(self) -> Box<Self::Pointee> {
let alloc = alloc(Layout::for_value_raw(self)); // TODO: _raw
let alloc = alloc(Layout::for_value(&*self));
self.copy_val_to(alloc); self.copy_val_to(alloc);
Box::from_raw(alloc.with_meta_from(self)) Box::from_raw(alloc.with_meta_from(self))
} }
@ -83,7 +88,7 @@ impl<T: ?Sized> PtrExt for *mut T {
type Pointee = T; type Pointee = T;
fn addr(self) -> usize { fn addr(self) -> usize {
self.to_raw_parts().0 as usize self.data_ptr() as usize
} }
fn align_up(self, align: usize) -> Self { fn align_up(self, align: usize) -> Self {
@ -94,12 +99,15 @@ impl<T: ?Sized> PtrExt for *mut T {
self.with_addr(addr.addr()) self.with_addr(addr.addr())
} }
fn with_addr(self, addr: usize) -> Self { fn with_addr(mut self, addr: usize) -> Self {
ptr::from_raw_parts_mut(addr as _, self.to_raw_parts().1) // TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
unsafe { *addr_of_mut!(self).cast() = addr }
self
} }
unsafe fn get_end(self) -> Self { unsafe fn get_end(self) -> Self {
self.add_bytes(size_of_val_raw(self)) // TODO: _raw
self.add_bytes(size_of_val(&*self))
} }
fn add_bytes(self, offset: usize) -> Self { fn add_bytes(self, offset: usize) -> Self {
@ -115,11 +123,13 @@ impl<T: ?Sized> PtrExt for *mut T {
} }
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) { unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
self.copy_bytes_to(dest, size_of_val_raw(self)); // TODO: _raw
self.copy_bytes_to(dest, size_of_val(&*self));
} }
unsafe fn read_to_box(self) -> Box<Self::Pointee> { unsafe fn read_to_box(self) -> Box<Self::Pointee> {
let alloc = alloc(Layout::for_value_raw(self)); // TODO: _raw
let alloc = alloc(Layout::for_value(&*self));
self.copy_val_to(alloc); self.copy_val_to(alloc);
Box::from_raw(alloc.with_meta_from(self)) Box::from_raw(alloc.with_meta_from(self))
} }
@ -129,22 +139,20 @@ impl<T: ?Sized> PtrExt for *mut T {
pub trait ConstPtrExt: Sealed { pub trait ConstPtrExt: Sealed {
fn data_ptr(self) -> *const (); fn data_ptr(self) -> *const ();
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U;
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U; fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U;
} }
impl<T: ?Sized> ConstPtrExt for *const T { impl<T: ?Sized> ConstPtrExt for *const T {
fn data_ptr(self) -> *const () { fn data_ptr(self) -> *const () {
self.to_raw_parts().0 self.cast()
} }
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U { // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U {
ptr::from_raw_parts(self.data_ptr(), meta) // ptr::from_raw_parts(self.data_ptr(), meta)
} // }
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U { fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U {
self.with_meta(ptr.to_raw_parts().1) ptr.with_addr_from(self)
} }
} }
@ -152,21 +160,21 @@ impl<T: ?Sized> ConstPtrExt for *const T {
pub trait MutPtrExt: Sealed { pub trait MutPtrExt: Sealed {
fn data_ptr(self) -> *mut (); fn data_ptr(self) -> *mut ();
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U; // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U;
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U; fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U;
} }
impl<T: ?Sized> MutPtrExt for *mut T { impl<T: ?Sized> MutPtrExt for *mut T {
fn data_ptr(self) -> *mut () { fn data_ptr(self) -> *mut () {
self.to_raw_parts().0 self.cast()
} }
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U { // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U {
ptr::from_raw_parts_mut(self.data_ptr(), meta) // ptr::from_raw_parts_mut(self.data_ptr(), meta)
} // }
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U { fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
self.with_meta(ptr.to_raw_parts().1) ptr.with_addr_from(self) as _
} }
} }

View file

@ -32,9 +32,9 @@ fn box_push() {
#[test] #[test]
fn unsize_push() { fn unsize_push() {
let mut vec: Vec<dyn Debug> = Vec::new(); let mut vec: Vec<dyn Debug> = Vec::new();
vec.push_unsize(1); vec.push_unsize_stable(1, |v| v as _);
vec.push_unsize(String::from("foo")); vec.push_unsize_stable(String::from("foo"), |v| v as _);
vec.push_unsize(true); vec.push_unsize_stable(true, |v| v as _);
assert_eq!(vec.debug(), "[1, \"foo\", true]"); assert_eq!(vec.debug(), "[1, \"foo\", true]");
} }
@ -69,11 +69,11 @@ fn dropped() {
let vec: Vec<dyn Debug> = vec![unsized: 1, FunkyDrop, true]; let vec: Vec<dyn Debug> = vec![unsized: 1, FunkyDrop, true];
assert_eq!(DROPPED.load(Ordering::SeqCst), false); assert!(!DROPPED.load(Ordering::SeqCst));
drop(vec); drop(vec);
assert_eq!(DROPPED.load(Ordering::SeqCst), true); assert!(DROPPED.load(Ordering::SeqCst));
} }
#[test] #[test]
@ -92,7 +92,7 @@ fn index() {
assert_eq!(vec[0], 3); assert_eq!(vec[0], 3);
assert_eq!(vec[1], 5); assert_eq!(vec[1], 5);
assert_eq!(vec[2], 7); assert_eq!(vec[2], 7);
vec[3]; let _ = vec[3];
} }
#[test] #[test]
@ -128,21 +128,24 @@ fn iteration() {
#[test] #[test]
fn zst() { fn zst() {
let vec: Vec<()> = vec![(), (), ()]; #[derive(Debug, PartialEq, Eq)]
struct Zst;
assert_eq!(vec[1], ()); let vec: Vec<Zst> = vec![Zst, Zst, Zst];
assert_eq!(vec[1], Zst);
for el in vec.iter() { for el in vec.iter() {
drop(el); let _ = el;
} }
assert_eq!(vec.debug(), "[(), (), ()]"); assert_eq!(vec.debug(), "[Zst, Zst, Zst]");
let vec: Vec<dyn Debug> = vec![unsized: (), (), ()]; let vec: Vec<dyn Debug> = vec![unsized: Zst, (), Zst];
assert_eq!(vec[1].debug(), "()"); assert_eq!(vec[1].debug(), "()");
for el in vec.iter() { for el in vec.iter() {
drop(el); let _ = el;
} }
assert_eq!(vec.debug(), "[(), (), ()]"); assert_eq!(vec.debug(), "[Zst, (), Zst]");
} }
#[test] #[test]
@ -190,8 +193,8 @@ fn with_capacity() {
#[test] #[test]
fn unsize() { fn unsize() {
let vec = vec![1, 2, 3]; let vec = vec![1, 2, 3];
let mut vec: Vec<dyn Debug> = vec.unsize(); let mut vec: Vec<dyn Debug> = vec.unsize_stable(|v| v as _);
vec.push_unsize(String::from("foo")); vec.push_unsize_stable(String::from("foo"), |v| v as _);
assert_eq!(vec.debug(), "[1, 2, 3, \"foo\"]"); assert_eq!(vec.debug(), "[1, 2, 3, \"foo\"]");
} }