Verify wrapper mismatch preservation
This commit is contained in:
+10
-2
@@ -90,6 +90,9 @@ macro_rules! define_thread_safe_erased_vec {
|
||||
}
|
||||
|
||||
/// Clear the vector and access its allocation as a vector of `T`.
|
||||
///
|
||||
/// A layout mismatch returns `None` without changing the erased
|
||||
/// vector.
|
||||
pub fn try_as_type<T>(&mut self) -> Option<ContentGuard<'_, T>>
|
||||
where
|
||||
T: $first_bound $(+ $remaining_bound)* + 'static,
|
||||
@@ -100,7 +103,8 @@ macro_rules! define_thread_safe_erased_vec {
|
||||
/// Clear the vector and access its allocation as a vector of `T`.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `T` does not have the erased allocation's layout.
|
||||
/// Panics if `T` does not have the erased allocation's layout. A
|
||||
/// layout-mismatch panic leaves the erased vector unchanged.
|
||||
pub fn as_type<T>(&mut self) -> ContentGuard<'_, T>
|
||||
where
|
||||
T: $first_bound $(+ $remaining_bound)* + 'static,
|
||||
@@ -111,6 +115,9 @@ macro_rules! define_thread_safe_erased_vec {
|
||||
/// Clear the vector and access its allocation using a possibly
|
||||
/// non-`'static` type that does not need drop.
|
||||
///
|
||||
/// A layout mismatch returns `None` without changing the erased
|
||||
/// vector.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `T` needs drop.
|
||||
pub fn try_as_type_scoped<T>(&mut self) -> Option<ContentGuard<'_, T>>
|
||||
@@ -125,7 +132,8 @@ macro_rules! define_thread_safe_erased_vec {
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `T` needs drop or does not have the erased allocation's
|
||||
/// layout.
|
||||
/// layout. A layout-mismatch panic leaves the erased vector
|
||||
/// unchanged.
|
||||
pub fn as_type_scoped<T>(&mut self) -> ContentGuard<'_, T>
|
||||
where
|
||||
T: $first_bound $(+ $remaining_bound)*,
|
||||
|
||||
@@ -160,6 +160,40 @@ macro_rules! assert_thread_safe_erased_vec_api {
|
||||
let mut erased = <$wrapper>::new(Vec::<u32>::new());
|
||||
assert!(erased.try_as_type::<u64>().is_none());
|
||||
|
||||
let retained = Arc::new(7_i32);
|
||||
let mut retained_values = Vec::with_capacity(4);
|
||||
retained_values.push(Arc::clone(&retained));
|
||||
let retained_ptr = retained_values.as_ptr();
|
||||
let retained_capacity = retained_values.capacity();
|
||||
let mut erased = <$wrapper>::new(retained_values);
|
||||
|
||||
assert!(erased.try_as_type::<u8>().is_none());
|
||||
assert!(
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let _ = erased.as_type::<u8>();
|
||||
}))
|
||||
.is_err()
|
||||
);
|
||||
assert!(erased.try_as_type_scoped::<u8>().is_none());
|
||||
assert!(
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let _ = erased.as_type_scoped::<u8>();
|
||||
}))
|
||||
.is_err()
|
||||
);
|
||||
assert_eq!(erased.layout(), Layout::new::<Arc<i32>>());
|
||||
assert_eq!(erased.length(), 1);
|
||||
assert_eq!(erased.capacity(), retained_capacity);
|
||||
assert_eq!(Arc::strong_count(&retained), 2);
|
||||
|
||||
{
|
||||
// SAFETY: Every failed probe preserved the original Arc<i32> type.
|
||||
let guard = unsafe { erased.cast_type::<Arc<i32>>() };
|
||||
assert_eq!(guard.as_slice().as_ptr(), retained_ptr);
|
||||
}
|
||||
drop(erased);
|
||||
assert_eq!(Arc::strong_count(&retained), 1);
|
||||
|
||||
let mut erased = <$wrapper>::new(vec![1_u32]);
|
||||
// SAFETY: The erased elements are still `u32`.
|
||||
assert_eq!(unsafe { erased.cast_type::<u32>() }.as_slice(), &[1_u32]);
|
||||
|
||||
Reference in New Issue
Block a user