From a6884257733b9852b8bb63d8aceeaf9616586423 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sat, 18 May 2024 09:53:18 -0700 Subject: [PATCH] [error] Implement std::error::Error on errors While we're here, also relax `Dispaly for AlignmentError` to permit `Dst: ?Sized` in exchange for `Dst: KnownLayout`. This is an important relaxation since our APIs permit performing conversions into unsized destination types with runtime alignment checking. Makes progress on #1297 --- Cargo.toml | 3 ++- src/error.rs | 34 +++++++++++++++++++++++++++++----- src/lib.rs | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84b61e9cb78..60dc116f43e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,10 +60,11 @@ alloc = [] derive = ["zerocopy-derive"] simd = [] simd-nightly = ["simd"] +std-error = ["alloc"] # This feature depends on all other features that work on the stable compiler. # We make no stability guarantees about this feature; it may be modified or # removed at any time. -__internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd"] +__internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd", "std-error"] [dependencies] zerocopy-derive = { version = "=0.8.0-alpha.14", path = "zerocopy-derive", optional = true } diff --git a/src/error.rs b/src/error.rs index fff9e4d36e9..d30d8dee034 100644 --- a/src/error.rs +++ b/src/error.rs @@ -25,9 +25,9 @@ use core::{convert::Infallible, fmt, marker::PhantomData, ops::Deref}; -use crate::TryFromBytes; #[cfg(doc)] use crate::{FromBytes, Ref}; +use crate::{KnownLayout, TryFromBytes}; /// Zerocopy's generic error type. /// @@ -82,6 +82,15 @@ impl fmt::Display for Convert } } +#[cfg(feature = "std-error")] +impl std::error::Error for ConvertError +where + A: fmt::Display + fmt::Debug, + S: fmt::Display + fmt::Debug, + V: fmt::Display + fmt::Debug, +{ +} + /// The error emitted if the conversion source is improperly aligned. #[derive(PartialEq, Eq)] pub struct AlignmentError { @@ -126,9 +135,10 @@ impl fmt::Debug for AlignmentError { // The bounds on this impl are intentionally conservative, and can be relaxed // either once a `?Sized` alignment accessor is stabilized, or by storing the // alignment as a runtime value. -impl fmt::Display for AlignmentError +impl fmt::Display for AlignmentError where Src: Deref, + Dst: KnownLayout, { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -139,14 +149,22 @@ where f.write_str("the conversion failed because the address of the source (a multiple of ")?; addr_align.fmt(f)?; f.write_str(") is not a multiple of the alignment (")?; - core::mem::align_of::().fmt(f)?; + ::LAYOUT.align.get().fmt(f)?; f.write_str(") of the destination type: ")?; f.write_str(core::any::type_name::())?; Ok(()) } } -impl From> +#[cfg(feature = "std-error")] +impl std::error::Error for AlignmentError +where + Src: Deref, + Dst: KnownLayout, +{ +} + +impl From> for ConvertError, S, V> { #[inline] @@ -216,7 +234,10 @@ where } } -impl From> for ConvertError, V> { +#[cfg(feature = "std-error")] +impl std::error::Error for SizeError where Src: Deref {} + +impl From> for ConvertError, V> { #[inline] fn from(err: SizeError) -> Self { Self::Size(err) @@ -274,6 +295,9 @@ where } } +#[cfg(feature = "std-error")] +impl std::error::Error for ValidityError where Src: Deref {} + impl From> for ConvertError> { diff --git a/src/lib.rs b/src/lib.rs index 084d5fe7432..7627a4b6c2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,7 +255,7 @@ clippy::arithmetic_side_effects, clippy::indexing_slicing, ))] -#![cfg_attr(not(test), no_std)] +#![cfg_attr(not(any(test, feature = "std-error")), no_std)] #![cfg_attr( all(feature = "simd-nightly", any(target_arch = "x86", target_arch = "x86_64")), feature(stdarch_x86_avx512)