1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Compile-time trait bound verification.
//!
//! These tests contain no runtime assertions. They exist purely to make the
//! compiler verify that `Error<E>` implements the correct set of traits for
//! representative instantiations of `E`. If any impl is accidentally removed,
//! a bound is incorrectly tightened, or a `cfg` gate is misapplied, this
//! file will fail to compile — surfacing the regression at `cargo test` time
//! rather than at a downstream consumer's build.
//!
//! The `static_assertions` crate is used for `assert_impl_all!` and
//! `assert_not_impl_any!`. These expand to zero-cost compile-time checks.
//!
//! Test matrix:
//!
//! | Assertion | `E` | Trait(s) | Feature gate |
//! |---|---|---|---|
//! | Send + Sync | `io::Error` | auto-trait derivation for a common E | none |
//! | Send + Sync | `String` | auto-trait derivation for an owned heap type | none |
//! | Send + Sync | `Arc<str>` | auto-trait derivation for a shared ref type | none |
//! | !Send | `*const u8` | auto-trait NOT derived when E is !Send | none |
//! | std::error::Error | `io::Error` | std feature impl present | `std` |
//! | std::error::Error | `Error<io::Error>` | nested chain is also Error | `std` |
//! | Display + Debug | `io::Error` | fmt impls always present | none |
//! | Display + Debug | `u32` | fmt impls work for non-Error E | none |
//! | Clone | `u32` | Clone derived when E: Clone | none |
//! | PartialEq + Eq | `u32` | Eq derived when E: Eq | none |
//! | !Clone | `io::Error` | Clone NOT derived when E: !Clone | none |
//! | !PartialEq | `io::Error` | PartialEq NOT derived when E: !PartialEq | none |
//! | !From<E> | `io::Error` | implicit From conversion absent by design | none |
//! | UnwindSafe | `u32`, `String` | unwind safety mirrors E | `std` |
use Error;
use ;
use io;
use Arc;
// ─────────────────────────────────────────────────────────────────────────────
// Send + Sync
//
// `Error<E>` must be Send when E: Send, and Sync when E: Sync.
// These are auto-traits derived from E and the internal `&'static str` context
// field, which is always Send + Sync. We verify for three representative E
// types to catch any accidental introduction of a !Send or !Sync field.
// ─────────────────────────────────────────────────────────────────────────────
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
// `Error<*const u8>` must NOT be Send or Sync because raw pointers are
// neither. This verifies that auto-trait derivation is conditional on E and
// not unconditionally asserted anywhere in the crate.
assert_not_impl_any!;
// ─────────────────────────────────────────────────────────────────────────────
// Display
//
// Implemented for all E: Display, unconditionally via `core::fmt`.
// Does not require the `std` or `alloc` feature. Does not require E to
// implement std::error::Error — only E: Display is needed.
// ─────────────────────────────────────────────────────────────────────────────
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
// ─────────────────────────────────────────────────────────────────────────────
// Debug
//
// Implemented for all E: Debug, unconditionally via `core::fmt`.
// ─────────────────────────────────────────────────────────────────────────────
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
// ─────────────────────────────────────────────────────────────────────────────
// Clone
//
// Implemented only when E: Clone. io::Error does not implement Clone,
// so Error<io::Error> must not implement Clone.
// ─────────────────────────────────────────────────────────────────────────────
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_not_impl_any!;
// ─────────────────────────────────────────────────────────────────────────────
// PartialEq + Eq
//
// Implemented only when E: PartialEq / Eq. io::Error implements neither.
// ─────────────────────────────────────────────────────────────────────────────
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_impl_all!;
assert_not_impl_any!;
// ─────────────────────────────────────────────────────────────────────────────
// From<E> is intentionally ABSENT
//
// Error<E> must not implement From<E>. If it did, the ? operator would
// silently construct an Error<E> with no context string — defeating the
// entire purpose of erra. This assertion locks that design decision in
// permanently. Removing it must require an explicit architectural decision.
// ─────────────────────────────────────────────────────────────────────────────
assert_not_impl_any!;
assert_not_impl_any!;
assert_not_impl_any!;
// ─────────────────────────────────────────────────────────────────────────────
// std-only assertions
//
// The following impls are gated on the `std` feature and must not be
// verified when compiling without it.
// ─────────────────────────────────────────────────────────────────────────────