diff --git a/src/cast.rs b/src/cast.rs index 5605c31..4a067c7 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -152,7 +152,7 @@ pub unsafe trait Container<'a>: Sized { /// The type class of this container. Used to limit which raw casts should be type Class: AssertClassContraints; /// The item type held within this container. - type Item: 'a; + type Item: 'a + ?Sized + ElementSize + ElementAlign; /// The 'raw' form of this container. Used to allow different containers to /// share the same `CastRaw` and `TryCastRaw` impls. type Raw: 'a + Copy; @@ -206,7 +206,7 @@ unsafe impl<'a, T: 'a> Container<'a> for &'a mut T { unsafe impl<'a, T: 'a> Container<'a> for &'a [T] { type Class = RefT; - type Item = T; + type Item = [T]; type Raw = (*const T, usize); type CastErr = OnlyErr; @@ -220,7 +220,7 @@ unsafe impl<'a, T: 'a> Container<'a> for &'a [T] { unsafe impl<'a, T: 'a> Container<'a> for &'a mut [T] { type Class = RefT; - type Item = T; + type Item = [T]; type Raw = (*mut T, usize); type CastErr = OnlyErr; @@ -277,7 +277,7 @@ unsafe impl<'a, T: 'a> Container<'a> for NonNull { #[cfg(feature = "non_null_slice_cast")] unsafe impl<'a, T: 'a> Container<'a> for NonNull<[T]> { type Class = NonNullT; - type Item = T; + type Item = [T]; type Raw = (*mut T, usize); type CastErr = OnlyErr; @@ -359,7 +359,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Box { #[cfg(feature = "extern_crate_alloc")] unsafe impl<'a, T: 'a> Container<'a> for Box<[T]> { type Class = BoxT; - type Item = T; + type Item = [T]; type Raw = (*const T, usize); type CastErr = ErrWithValue; @@ -401,7 +401,7 @@ unsafe impl<'a, T: 'a + Copy> Container<'a> for Cow<'a, T> { #[cfg(feature = "extern_crate_alloc")] unsafe impl<'a, T: 'a + Copy> Container<'a> for Cow<'a, [T]> { type Class = CowT; - type Item = T; + type Item = [T]; type Raw = RawCow<(*const T, usize), (*const T, usize, usize)>; type CastErr = ErrWithValue; @@ -437,7 +437,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Rc { #[cfg(feature = "extern_crate_alloc")] unsafe impl<'a, T: 'a> Container<'a> for Rc<[T]> { type Class = RcT; - type Item = T; + type Item = [T]; type Raw = (*mut T, usize); type CastErr = ErrWithValue; @@ -483,7 +483,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Arc { #[cfg(feature = "extern_crate_alloc")] unsafe impl<'a, T: 'a> Container<'a> for Arc<[T]> { type Class = ArcT; - type Item = T; + type Item = [T]; type Raw = (*mut T, usize); type CastErr = ErrWithValue; @@ -882,31 +882,35 @@ where } /// Checks any constraints the container requires when casting between types. -pub trait AssertClassContraints { +pub trait AssertClassContraints { const ASSERT: () = (); } -impl AssertClassContraints for RefT {} -impl AssertClassContraints for PtrT {} -impl AssertClassContraints for NonNullT {} +impl AssertClassContraints for RefT {} +impl AssertClassContraints for PtrT {} +impl AssertClassContraints for NonNullT {} impl AssertClassContraints for AtomicPtrT {} -impl<'a, C, T, U> AssertClassContraints for OptionT +impl<'a, C, T: ?Sized, U: ?Sized> AssertClassContraints for OptionT where C: AssertClassContraints, { const ASSERT: () = C::ASSERT; } -impl<'a, C, T, U> AssertClassContraints for PinT +impl<'a, C, T: ?Sized, U: ?Sized> AssertClassContraints for PinT where C: AssertClassContraints, { const ASSERT: () = C::ASSERT; } #[cfg(feature = "extern_crate_alloc")] -impl AssertClassContraints for BoxT { +impl + AssertClassContraints for BoxT +{ const ASSERT: () = static_assert!(AssertSameAlign(T, U)); } #[cfg(feature = "extern_crate_alloc")] -impl AssertClassContraints for RcT { +impl + AssertClassContraints for RcT +{ const ASSERT: () = static_assert!(AssertSameAlign(T, U)); } #[cfg(feature = "extern_crate_alloc")] @@ -914,7 +918,9 @@ impl AssertClassContraints for RcWeakT { const ASSERT: () = static_assert!(AssertSameAlign(T, U)); } #[cfg(feature = "extern_crate_alloc")] -impl AssertClassContraints for ArcT { +impl + AssertClassContraints for ArcT +{ const ASSERT: () = static_assert!(AssertSameAlign(T, U)); } #[cfg(feature = "extern_crate_alloc")] diff --git a/src/static_assert.rs b/src/static_assert.rs index d046f23..8e6d9e8 100644 --- a/src/static_assert.rs +++ b/src/static_assert.rs @@ -9,34 +9,57 @@ use core::mem::{align_of, size_of}; -pub trait AssertNonMixedZeroSize: Sized { +pub trait ElementSize { + const VALUE: usize; +} +impl ElementSize for T { + const VALUE: usize = size_of::(); +} +impl ElementSize for [T] { + const VALUE: usize = size_of::(); +} + +pub trait ElementAlign { + const VALUE: usize; +} +impl ElementAlign for T { + const VALUE: usize = align_of::(); +} +impl ElementAlign for [T] { + const VALUE: usize = align_of::(); +} + +pub trait AssertNonMixedZeroSize: ElementSize { const ASSERT: () = { - if (size_of::() == 0) != (size_of::() == 0) { + if (Self::VALUE == 0) != (T::VALUE == 0) { panic!( "Attempt to cast between a zero-sized type and a non-zero-sized type" ); } }; } -impl AssertNonMixedZeroSize for T {} +impl AssertNonMixedZeroSize + for T +{ +} -pub trait AssertNonZeroSize: Sized { +pub trait AssertNonZeroSize: ElementSize { const ASSERT: () = { - if size_of::() == 0 { + if Self::VALUE == 0 { panic!("Attempt to cast a zero-sized type"); } }; } -impl AssertNonZeroSize for T {} +impl AssertNonZeroSize for T {} -pub trait AssertSameSize: Sized { +pub trait AssertSameSize: ElementSize { const ASSERT: () = { - if size_of::() == size_of::() { + if Self::VALUE != T::VALUE { panic!("Attempt to cast between two types with different sizes"); } }; } -impl AssertSameSize for T {} +impl AssertSameSize for T {} pub trait AssertMaxSize: Sized { const ASSERT: () = { @@ -47,34 +70,41 @@ pub trait AssertMaxSize: Sized { } impl AssertMaxSize for T {} -pub trait AssertSizeMultipleOf: Sized { +pub trait AssertSizeMultipleOf: ElementSize { const ASSERT: () = { - if size_of::() != size_of::() - && size_of::() % size_of::() != 0 - { + if Self::VALUE != T::VALUE && Self::VALUE % T::VALUE != 0 { panic!("Attempt to cast from a type which is not a multiple of the target's size"); } }; } -impl AssertSizeMultipleOf for T {} +impl AssertSizeMultipleOf + for T +{ +} -pub trait AssertSameAlign: Sized { +pub trait AssertSameAlign: ElementAlign { const ASSERT: () = { - if align_of::() == align_of::() { + if Self::VALUE != T::VALUE { panic!("Attempt to cast between two types with different alignments"); } }; } -impl AssertSameAlign for T {} +impl AssertSameAlign + for T +{ +} -pub trait AssertMinAlign: Sized { +pub trait AssertMinAlign: ElementAlign { const ASSERT: () = { - if align_of::() < align_of::() { + if Self::VALUE < T::VALUE { panic!("Attempt to cast to a type with a larger alignment"); } }; } -impl AssertMinAlign for T {} +impl AssertMinAlign + for T +{ +} macro_rules! static_assert { ($assertion:ident($ty:ty $(, $($args:tt)*)?)) => {{