@@ -4,8 +4,6 @@ use core::result;
4
4
use serde:: de;
5
5
use serde:: ser;
6
6
#[ cfg( feature = "std" ) ]
7
- use std:: error;
8
- #[ cfg( feature = "std" ) ]
9
7
use std:: io;
10
8
11
9
/// This type represents all possible errors that can occur when serializing or deserializing CBOR
@@ -192,9 +190,31 @@ impl Error {
192
190
}
193
191
}
194
192
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 ) > {
198
218
match self . 0 . code {
199
219
ErrorCode :: Io ( ref err) => Some ( err) ,
200
220
_ => None ,
0 commit comments