Skip to content
This repository was archived by the owner on Aug 15, 2021. It is now read-only.

Commit 4dca7bf

Browse files
committed
Use serde::ser::StdError shim type rather than std::error::Error
This is for `alloc` vs. `std` modes compatibility, a code comment explains in detail the purpose of this, which is admittedly subtle.
1 parent d012830 commit 4dca7bf

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/error.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ use core::result;
44
use serde::de;
55
use serde::ser;
66
#[cfg(feature = "std")]
7-
use std::error;
8-
#[cfg(feature = "std")]
97
use std::io;
108

119
/// This type represents all possible errors that can occur when serializing or deserializing CBOR
@@ -192,9 +190,31 @@ impl Error {
192190
}
193191
}
194192

195-
#[cfg(feature = "std")]
196-
impl error::Error for Error {
197-
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
193+
// Note: serde::ser::StdError is a compatibility type introduced here:
194+
// https://github.com/serde-rs/serde/releases/tag/v1.0.100
195+
// In case of `serde/std`, this is just `std::error::Error`,
196+
// in case of `serde/alloc`, this is a trait that looks identical.
197+
// The purpose of this is to try to make it so that if one, no_std crate in your build
198+
// relies on `cbor/alloc`, and does not require `cbor/std`, but e.g. a third party crate
199+
// from crates.io turns on `serde/std` (and there are many like this) the build can still succeed.
200+
// Normally your build will fail in this case because in `serde/std`, serde enforces
201+
// a trait bound that your serializer's error type MUST implement the serde::ser::StdError.
202+
// (formerly it was just std::error::Error).
203+
// But in a `cbor/alloc` config it is impossible for you to access std::error::Error.
204+
// This is why dtolnay added the serde::ser::StdError compat shim.
205+
//
206+
// Without a shim like this, any `no_std` + alloc crate that wants to use cbor would be required to
207+
// expose an `std` and `alloc` feature set and "forward" those settings to `cbor`, even if
208+
// there is no technical reason in that crate to do so. And their downstreams must
209+
// similarlly expose these features, and diligently forward them to their dependencies.
210+
// Debugging that stuff in a large project is hard and this causes a lot of pain.
211+
//
212+
// This is expected to change to std::error::Error again if the rust lang team manages
213+
// to move std::error::Error to the alloc crate.
214+
// https://github.com/rust-lang/rust/issues/62502
215+
#[cfg(any(feature = "std", feature = "alloc"))]
216+
impl serde::ser::StdError for Error {
217+
fn source(&self) -> Option<&(dyn serde::ser::StdError + 'static)> {
198218
match self.0.code {
199219
ErrorCode::Io(ref err) => Some(err),
200220
_ => None,

0 commit comments

Comments
 (0)