Skip to content

Commit 3b24e42

Browse files
committed
Make DeserializeInner unsafe to implement due to the new covariance constraint on its DeserType
1 parent 7e42b45 commit 3b24e42

File tree

11 files changed

+41
-28
lines changed

11 files changed

+41
-28
lines changed

epserde-derive/src/lib.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,9 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
484484
}
485485
}
486486

487+
// SAFETY: &'epserde_desertype Self is covariant
487488
#[automatically_derived]
488-
impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des
489+
unsafe impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des
489490
{
490491
unsafe fn _deserialize_full_inner(
491492
backend: &mut impl epserde::deser::ReadWithPos,
@@ -540,8 +541,9 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
540541
}
541542
}
542543

544+
// SAFETY: #name is a struct, so it is covariant
543545
#[automatically_derived]
544-
impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
546+
unsafe impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
545547
unsafe fn _deserialize_full_inner(
546548
backend: &mut impl epserde::deser::ReadWithPos,
547549
) -> core::result::Result<Self, epserde::deser::Error> {
@@ -824,8 +826,9 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
824826
}
825827
}
826828

829+
// SAFETY: &'epserde_desertype Self is covariant
827830
#[automatically_derived]
828-
impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
831+
unsafe impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
829832
unsafe fn _deserialize_full_inner(
830833
backend: &mut impl epserde::deser::ReadWithPos,
831834
) -> core::result::Result<Self, epserde::deser::Error> {
@@ -878,8 +881,9 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
878881
Ok(())
879882
}
880883
}
884+
// SAFETY: #name is an enum, so it is covariant
881885
#[automatically_derived]
882-
impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
886+
unsafe impl<#generics_deserialize> epserde::deser::DeserializeInner for #name<#concat_generics> #where_clause_des {
883887
unsafe fn _deserialize_full_inner(
884888
backend: &mut impl epserde::deser::ReadWithPos,
885889
) -> core::result::Result<Self, epserde::deser::Error> {

epserde/src/deser/mem_case.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ impl<'a, S: DeserializeInner> MemCase<'a, S> {
139139
pub fn borrow<'this>(&'this self) -> &'this <S as DeserializeInner>::DeserType<'this> {
140140
// SAFETY: 'a outlives 'this, and <S as DeserializeInner>::DeserType is required to be
141141
// covariant (ie. it's a normal structure and not, say, a closure with 'this as argument)
142-
// TODO: document in DeserializeInner that its DeserType must be covariant
143142
unsafe {
144143
core::mem::transmute::<
145144
&'this <S as DeserializeInner>::DeserType<'a>,

epserde/src/deser/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub type DeserType<'a, T> = <T as DeserializeInner>::DeserType<'a>;
6464
/// incompatible structures using the same code, or cause undefined behavior
6565
/// by loading data with an incorrect alignment.
6666
/// - Memory-mapped files might be modified externally.
67+
/// - [`Self::DeserType`] must be covariant (ie. behave like a structure,
68+
/// not a closure with a generic argument)
6769
pub trait Deserialize: DeserializeInner {
6870
/// Fully deserialize a structure of this type from the given backend.
6971
///
@@ -253,7 +255,11 @@ pub trait Deserialize: DeserializeInner {
253255
/// the user from modifying the methods in [`Deserialize`].
254256
///
255257
/// The user should not implement this trait directly, but rather derive it.
256-
pub trait DeserializeInner: Sized {
258+
///
259+
/// # Safety
260+
///
261+
/// See [`Deserialize`]
262+
pub unsafe trait DeserializeInner: Sized {
257263
/// The deserialization type associated with this type. It can be
258264
/// retrieved conveniently with the alias [`DeserType`].
259265
type DeserType<'a>;

epserde/src/impls/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<T: DeepCopy + SerializeInner, const N: usize> SerializeHelper<Deep> for [T;
7575
}
7676
}
7777

78-
impl<T: CopyType + DeserializeInner, const N: usize> DeserializeInner for [T; N]
78+
unsafe impl<T: CopyType + DeserializeInner, const N: usize> DeserializeInner for [T; N]
7979
where
8080
[T; N]: DeserializeHelper<<T as CopyType>::Copy, FullType = [T; N]>,
8181
{

epserde/src/impls/boxed_slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<T: DeepCopy + SerializeInner> SerializeHelper<Deep> for Box<[T]> {
6060
}
6161

6262
// This delegates to a private helper trait which we can specialize on in stable rust
63-
impl<T: DeserializeInner + CopyType> DeserializeInner for Box<[T]>
63+
unsafe impl<T: DeserializeInner + CopyType> DeserializeInner for Box<[T]>
6464
where
6565
Box<[T]>: DeserializeHelper<<T as CopyType>::Copy, FullType = Box<[T]>>,
6666
{

epserde/src/impls/prim.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ macro_rules! impl_prim_ser_des {
6767
}
6868
}
6969

70-
impl DeserializeInner for $ty {
70+
unsafe impl DeserializeInner for $ty {
7171
#[inline(always)]
7272
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<$ty> {
7373
let mut buf = [0; size_of::<$ty>()];
@@ -109,7 +109,7 @@ macro_rules! impl_nonzero_ser_des {
109109
}
110110
}
111111

112-
impl DeserializeInner for $ty {
112+
unsafe impl DeserializeInner for $ty {
113113
#[inline(always)]
114114
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<$ty> {
115115
let mut buf = [0; size_of::<$ty>()];
@@ -179,7 +179,7 @@ impl SerializeInner for bool {
179179
}
180180
}
181181

182-
impl DeserializeInner for bool {
182+
unsafe impl DeserializeInner for bool {
183183
#[inline(always)]
184184
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<bool> {
185185
Ok(u8::_deserialize_full_inner(backend)? != 0)
@@ -208,7 +208,7 @@ impl SerializeInner for char {
208208
}
209209
}
210210

211-
impl DeserializeInner for char {
211+
unsafe impl DeserializeInner for char {
212212
#[inline(always)]
213213
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
214214
Ok(char::from_u32(u32::_deserialize_full_inner(backend)?).unwrap())
@@ -235,7 +235,7 @@ impl SerializeInner for () {
235235
}
236236
}
237237

238-
impl DeserializeInner for () {
238+
unsafe impl DeserializeInner for () {
239239
#[inline(always)]
240240
unsafe fn _deserialize_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
241241
Ok(())
@@ -288,7 +288,7 @@ impl<T: ?Sized> SerializeInner for PhantomData<T> {
288288
}
289289
}
290290

291-
impl<T: ?Sized> DeserializeInner for PhantomData<T> {
291+
unsafe impl<T: ?Sized> DeserializeInner for PhantomData<T> {
292292
#[inline(always)]
293293
unsafe fn _deserialize_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
294294
Ok(PhantomData::<T>)
@@ -339,7 +339,7 @@ impl<T: SerializeInner + TypeHash + AlignHash> SerializeInner for Option<T> {
339339
}
340340
}
341341

342-
impl<T: DeserializeInner> DeserializeInner for Option<T> {
342+
unsafe impl<T: DeserializeInner> DeserializeInner for Option<T> {
343343
#[inline(always)]
344344
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
345345
let tag = u8::_deserialize_full_inner(backend)?;

epserde/src/impls/stdlib.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl<Idx: ZeroCopy + SerializeInner + TypeHash + AlignHash> SerializeInner
9494
}
9595
}
9696

97-
impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::Range<Idx> {
97+
unsafe impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::Range<Idx> {
9898
#[inline(always)]
9999
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
100100
let start = Idx::_deserialize_full_inner(backend)?;
@@ -126,7 +126,7 @@ impl<Idx: ZeroCopy + SerializeInner + TypeHash + AlignHash> SerializeInner
126126
}
127127
}
128128

129-
impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeFrom<Idx> {
129+
unsafe impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeFrom<Idx> {
130130
#[inline(always)]
131131
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
132132
let start = Idx::_deserialize_full_inner(backend)?;
@@ -158,7 +158,7 @@ impl<Idx: ZeroCopy + SerializeInner + TypeHash + AlignHash> SerializeInner
158158
}
159159
}
160160

161-
impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeInclusive<Idx> {
161+
unsafe impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeInclusive<Idx> {
162162
#[inline(always)]
163163
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
164164
let start = Idx::_deserialize_full_inner(backend)?;
@@ -194,7 +194,7 @@ impl<Idx: ZeroCopy + SerializeInner + TypeHash + AlignHash> SerializeInner
194194
}
195195
}
196196

197-
impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeTo<Idx> {
197+
unsafe impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeTo<Idx> {
198198
#[inline(always)]
199199
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
200200
let end = Idx::_deserialize_full_inner(backend)?;
@@ -224,7 +224,9 @@ impl<Idx: ZeroCopy + SerializeInner + TypeHash + AlignHash> SerializeInner
224224
}
225225
}
226226

227-
impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner for core::ops::RangeToInclusive<Idx> {
227+
unsafe impl<Idx: ZeroCopy + DeserializeInner> DeserializeInner
228+
for core::ops::RangeToInclusive<Idx>
229+
{
228230
#[inline(always)]
229231
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
230232
let end = Idx::_deserialize_full_inner(backend)?;
@@ -251,7 +253,7 @@ impl SerializeInner for core::ops::RangeFull {
251253
}
252254
}
253255

254-
impl DeserializeInner for core::ops::RangeFull {
256+
unsafe impl DeserializeInner for core::ops::RangeFull {
255257
#[inline(always)]
256258
unsafe fn _deserialize_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
257259
Ok(core::ops::RangeFull)
@@ -301,7 +303,7 @@ impl<T: SerializeInner + TypeHash + AlignHash> SerializeInner for core::ops::Bou
301303
}
302304
}
303305

304-
impl<T: DeserializeInner> DeserializeInner for core::ops::Bound<T> {
306+
unsafe impl<T: DeserializeInner> DeserializeInner for core::ops::Bound<T> {
305307
#[inline(always)]
306308
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
307309
let tag = u8::_deserialize_full_inner(backend)?;
@@ -376,7 +378,9 @@ impl<B: SerializeInner + TypeHash + AlignHash, C: SerializeInner + TypeHash + Al
376378
}
377379
}
378380

379-
impl<B: DeserializeInner, C: DeserializeInner> DeserializeInner for core::ops::ControlFlow<B, C> {
381+
unsafe impl<B: DeserializeInner, C: DeserializeInner> DeserializeInner
382+
for core::ops::ControlFlow<B, C>
383+
{
380384
#[inline(always)]
381385
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
382386
let tag = u8::_deserialize_full_inner(backend)?;

epserde/src/impls/string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl SerializeInner for String {
6565
}
6666
}
6767

68-
impl DeserializeInner for String {
68+
unsafe impl DeserializeInner for String {
6969
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
7070
let slice = deserialize_full_vec_zero(backend)?;
7171
Ok(String::from_utf8(slice).unwrap())
@@ -99,7 +99,7 @@ impl SerializeInner for Box<str> {
9999
}
100100
}
101101

102-
impl DeserializeInner for Box<str> {
102+
unsafe impl DeserializeInner for Box<str> {
103103
#[inline(always)]
104104
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
105105
Ok(String::_deserialize_full_inner(backend)?.into_boxed_str())

epserde/src/impls/tuple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ macro_rules! impl_tuples {
8787
}
8888
}
8989

90-
impl<T: ZeroCopy + TypeHash + AlignHash> DeserializeInner for ($($t,)*) {
90+
unsafe impl<T: ZeroCopy + TypeHash + AlignHash> DeserializeInner for ($($t,)*) {
9191
type DeserType<'a> = &'a ($($t,)*);
9292
unsafe fn _deserialize_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
9393
deserialize_full_zero::<($($t,)*)>(backend)

epserde/src/impls/vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl<T: DeepCopy + SerializeInner> SerializeHelper<Deep> for Vec<T> {
6666
}
6767

6868
// This delegates to a private helper trait which we can specialize on in stable rust
69-
impl<T: CopyType + DeserializeInner> DeserializeInner for Vec<T>
69+
unsafe impl<T: CopyType + DeserializeInner> DeserializeInner for Vec<T>
7070
where
7171
Vec<T>: DeserializeHelper<<T as CopyType>::Copy, FullType = Vec<T>>,
7272
{

0 commit comments

Comments
 (0)