Skip to content

Commit 258e479

Browse files
authored
Make errors Clone and relax PartialEq/Eq bounds (#2715)
* Fix spelling. * Make errors Clone. Manually implement PartialEq, Eq and Clone for types using SendSyncPhantomData. This is necessary because the default derive imposes an additional PartialEq/Eq/Clone bounds on the phantom type.
1 parent b4d3fba commit 258e479

File tree

4 files changed

+115
-22
lines changed

4 files changed

+115
-22
lines changed

src/error.rs

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ use crate::{FromBytes, Ref};
149149
/// - [`CastError`]: the error type of reference conversions
150150
/// - [`TryCastError`]: the error type of fallible reference conversions
151151
/// - [`TryReadError`]: the error type of fallible read conversions
152-
#[derive(PartialEq, Eq)]
152+
#[derive(PartialEq, Eq, Clone)]
153153
pub enum ConvertError<A, S, V> {
154154
/// The conversion source was improperly aligned.
155155
Alignment(A),
@@ -245,15 +245,14 @@ where
245245
}
246246

247247
/// The error emitted if the conversion source is improperly aligned.
248-
#[derive(PartialEq, Eq)]
249248
pub struct AlignmentError<Src, Dst: ?Sized> {
250249
/// The source value involved in the conversion.
251250
src: Src,
252251
/// The inner destination type involved in the conversion.
253252
///
254253
/// INVARIANT: An `AlignmentError` may only be constructed if `Dst`'s
255254
/// alignment requirement is greater than one.
256-
dst: SendSyncPhantomData<Dst>,
255+
_dst: SendSyncPhantomData<Dst>,
257256
}
258257

259258
impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
@@ -264,7 +263,7 @@ impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
264263
pub(crate) unsafe fn new_unchecked(src: Src) -> Self {
265264
// INVARIANT: The caller guarantees that `Dst`'s alignment requirement
266265
// is greater than one.
267-
Self { src, dst: SendSyncPhantomData::default() }
266+
Self { src, _dst: SendSyncPhantomData::default() }
268267
}
269268

270269
/// Produces the source underlying the failed conversion.
@@ -277,7 +276,7 @@ impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
277276
// INVARIANT: `with_src` doesn't change the type of `Dst`, so the
278277
// invariant that `Dst`'s alignment requirement is greater than one is
279278
// preserved.
280-
AlignmentError { src: new_src, dst: SendSyncPhantomData::default() }
279+
AlignmentError { src: new_src, _dst: SendSyncPhantomData::default() }
281280
}
282281

283282
/// Maps the source value associated with the conversion error.
@@ -302,7 +301,7 @@ impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
302301
/// ```
303302
#[inline]
304303
pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> AlignmentError<NewSrc, Dst> {
305-
AlignmentError { src: f(self.src), dst: SendSyncPhantomData::default() }
304+
AlignmentError { src: f(self.src), _dst: SendSyncPhantomData::default() }
306305
}
307306

308307
pub(crate) fn into<S, V>(self) -> ConvertError<Self, S, V> {
@@ -340,6 +339,22 @@ impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
340339
}
341340
}
342341

342+
impl<Src: Clone, Dst: ?Sized> Clone for AlignmentError<Src, Dst> {
343+
#[inline]
344+
fn clone(&self) -> Self {
345+
Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
346+
}
347+
}
348+
349+
impl<Src: PartialEq, Dst: ?Sized> PartialEq for AlignmentError<Src, Dst> {
350+
#[inline]
351+
fn eq(&self, other: &Self) -> bool {
352+
self.src == other.src
353+
}
354+
}
355+
356+
impl<Src: Eq, Dst: ?Sized> Eq for AlignmentError<Src, Dst> {}
357+
343358
impl<Src, Dst: ?Sized + Unaligned> From<AlignmentError<Src, Dst>> for Infallible {
344359
#[inline(always)]
345360
fn from(_: AlignmentError<Src, Dst>) -> Infallible {
@@ -411,17 +426,16 @@ impl<Src, Dst: ?Sized, S, V> From<AlignmentError<Src, Dst>>
411426
}
412427

413428
/// The error emitted if the conversion source is of incorrect size.
414-
#[derive(PartialEq, Eq)]
415429
pub struct SizeError<Src, Dst: ?Sized> {
416430
/// The source value involved in the conversion.
417431
src: Src,
418-
/// The inner destination type inolved in the conversion.
419-
dst: SendSyncPhantomData<Dst>,
432+
/// The inner destination type involved in the conversion.
433+
_dst: SendSyncPhantomData<Dst>,
420434
}
421435

422436
impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
423437
pub(crate) fn new(src: Src) -> Self {
424-
Self { src, dst: SendSyncPhantomData::default() }
438+
Self { src, _dst: SendSyncPhantomData::default() }
425439
}
426440

427441
/// Produces the source underlying the failed conversion.
@@ -432,7 +446,7 @@ impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
432446

433447
/// Sets the source value associated with the conversion error.
434448
pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> SizeError<NewSrc, Dst> {
435-
SizeError { src: new_src, dst: SendSyncPhantomData::default() }
449+
SizeError { src: new_src, _dst: SendSyncPhantomData::default() }
436450
}
437451

438452
/// Maps the source value associated with the conversion error.
@@ -458,12 +472,12 @@ impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
458472
/// ```
459473
#[inline]
460474
pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> SizeError<NewSrc, Dst> {
461-
SizeError { src: f(self.src), dst: SendSyncPhantomData::default() }
475+
SizeError { src: f(self.src), _dst: SendSyncPhantomData::default() }
462476
}
463477

464478
/// Sets the destination type associated with the conversion error.
465479
pub(crate) fn with_dst<NewDst: ?Sized>(self) -> SizeError<Src, NewDst> {
466-
SizeError { src: self.src, dst: SendSyncPhantomData::default() }
480+
SizeError { src: self.src, _dst: SendSyncPhantomData::default() }
467481
}
468482

469483
/// Converts the error into a general [`ConvertError`].
@@ -510,6 +524,22 @@ impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
510524
}
511525
}
512526

527+
impl<Src: Clone, Dst: ?Sized> Clone for SizeError<Src, Dst> {
528+
#[inline]
529+
fn clone(&self) -> Self {
530+
Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
531+
}
532+
}
533+
534+
impl<Src: PartialEq, Dst: ?Sized> PartialEq for SizeError<Src, Dst> {
535+
#[inline]
536+
fn eq(&self, other: &Self) -> bool {
537+
self.src == other.src
538+
}
539+
}
540+
541+
impl<Src: Eq, Dst: ?Sized> Eq for SizeError<Src, Dst> {}
542+
513543
impl<Src, Dst: ?Sized> fmt::Debug for SizeError<Src, Dst> {
514544
#[inline]
515545
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -555,17 +585,16 @@ impl<Src, Dst: ?Sized, A, V> From<SizeError<Src, Dst>> for ConvertError<A, SizeE
555585
}
556586

557587
/// The error emitted if the conversion source contains invalid data.
558-
#[derive(PartialEq, Eq)]
559588
pub struct ValidityError<Src, Dst: ?Sized + TryFromBytes> {
560589
/// The source value involved in the conversion.
561590
pub(crate) src: Src,
562-
/// The inner destination type inolved in the conversion.
563-
dst: SendSyncPhantomData<Dst>,
591+
/// The inner destination type involved in the conversion.
592+
_dst: SendSyncPhantomData<Dst>,
564593
}
565594

566595
impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> {
567596
pub(crate) fn new(src: Src) -> Self {
568-
Self { src, dst: SendSyncPhantomData::default() }
597+
Self { src, _dst: SendSyncPhantomData::default() }
569598
}
570599

571600
/// Produces the source underlying the failed conversion.
@@ -596,7 +625,7 @@ impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> {
596625
/// ```
597626
#[inline]
598627
pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> ValidityError<NewSrc, Dst> {
599-
ValidityError { src: f(self.src), dst: SendSyncPhantomData::default() }
628+
ValidityError { src: f(self.src), _dst: SendSyncPhantomData::default() }
600629
}
601630

602631
/// Converts the error into a general [`ConvertError`].
@@ -617,6 +646,22 @@ impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> {
617646
}
618647
}
619648

649+
impl<Src: Clone, Dst: ?Sized + TryFromBytes> Clone for ValidityError<Src, Dst> {
650+
#[inline]
651+
fn clone(&self) -> Self {
652+
Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
653+
}
654+
}
655+
656+
impl<Src: PartialEq, Dst: ?Sized + TryFromBytes> PartialEq for ValidityError<Src, Dst> {
657+
#[inline]
658+
fn eq(&self, other: &Self) -> bool {
659+
self.src == other.src
660+
}
661+
}
662+
663+
impl<Src: Eq, Dst: ?Sized + TryFromBytes> Eq for ValidityError<Src, Dst> {}
664+
620665
impl<Src, Dst: ?Sized + TryFromBytes> fmt::Debug for ValidityError<Src, Dst> {
621666
#[inline]
622667
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -996,6 +1041,48 @@ mod tests {
9961041
}
9971042
}
9981043

1044+
#[test]
1045+
fn test_eq_partial_eq_clone() {
1046+
// Test that all error types implement `Eq`, `PartialEq`
1047+
// and `Clone` if src does
1048+
// even if `Dst: !Eq`, `!PartialEq`, `!Clone`.
1049+
1050+
#[allow(dead_code)]
1051+
fn is_eq_partial_eq_clone<T: Eq + PartialEq + Clone>(_t: T) {}
1052+
1053+
#[allow(dead_code)]
1054+
fn alignment_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>(
1055+
err: AlignmentError<Src, Dst>,
1056+
) {
1057+
is_eq_partial_eq_clone(err)
1058+
}
1059+
1060+
#[allow(dead_code)]
1061+
fn size_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>(
1062+
err: SizeError<Src, Dst>,
1063+
) {
1064+
is_eq_partial_eq_clone(err)
1065+
}
1066+
1067+
#[allow(dead_code)]
1068+
fn validity_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>(
1069+
err: ValidityError<Src, Dst>,
1070+
) {
1071+
is_eq_partial_eq_clone(err)
1072+
}
1073+
1074+
#[allow(dead_code)]
1075+
fn convert_error_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>(
1076+
err: ConvertError<
1077+
AlignmentError<Src, Dst>,
1078+
SizeError<Src, Dst>,
1079+
ValidityError<Src, Dst>,
1080+
>,
1081+
) {
1082+
is_eq_partial_eq_clone(err)
1083+
}
1084+
}
1085+
9991086
#[test]
10001087
fn alignment_display() {
10011088
#[repr(C, align(128))]

src/impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
812812
//
813813
// `is_bit_valid` is documented as panicking or failing to monomorphize
814814
// if called with a shared-aliased pointer on a type containing an
815-
// `UnsafeCell`. In practice, it will always be a monorphization error.
815+
// `UnsafeCell`. In practice, it will always be a monomorphization error.
816816
// Since `is_bit_valid` is `#[doc(hidden)]` and only called directly
817817
// from this crate, we only need to worry about our own code incorrectly
818818
// calling `UnsafeCell::is_bit_valid`. The post-monomorphization error

src/pointer/ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ mod _external {
118118
/// referent of a `Ptr<T, I: Invariants<Validity = V>>`. Since this copy
119119
/// does not change `I::Validity` or `T`, `S(T, I::Validity)` is also
120120
/// unchanged.
121-
///
121+
///
122122
/// We are required to guarantee that the referents of the original `Ptr`
123123
/// and of the copy (which, of course, are actually the same since they
124124
/// live in the same byte address range) both remain in the set `S(T,

src/util/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,19 @@ impl<T: ?Sized> Default for SendSyncPhantomData<T> {
3939
}
4040

4141
impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
42-
fn eq(&self, other: &Self) -> bool {
43-
self.0.eq(&other.0)
42+
fn eq(&self, _other: &Self) -> bool {
43+
true
4444
}
4545
}
4646

4747
impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
4848

49+
impl<T: ?Sized> Clone for SendSyncPhantomData<T> {
50+
fn clone(&self) -> Self {
51+
SendSyncPhantomData(PhantomData)
52+
}
53+
}
54+
4955
pub(crate) trait AsAddress {
5056
fn addr(self) -> usize;
5157
}

0 commit comments

Comments
 (0)