facet_reflect/error.rs
1use facet_core::{Characteristic, EnumType, FieldError, Shape, TryFromError};
2use owo_colors::OwoColorize;
3
4/// Errors that can occur when reflecting on types.
5#[derive(Clone)]
6pub enum ReflectError<'shape> {
7 /// Tried to set an enum to a variant that does not exist
8 NoSuchVariant {
9 /// The enum definition containing all known variants.
10 enum_type: EnumType<'shape>,
11 },
12
13 /// Tried to get the wrong shape out of a value — e.g. we were manipulating
14 /// a `String`, but `.get()` was called with a `u64` or something.
15 WrongShape {
16 /// The expected shape of the value.
17 expected: &'shape Shape<'shape>,
18 /// The actual shape of the value.
19 actual: &'shape Shape<'shape>,
20 },
21
22 /// Attempted to perform an operation that expected a struct or something
23 WasNotA {
24 /// The name of the expected type.
25 expected: &'shape str,
26
27 /// The type we got instead
28 actual: &'shape Shape<'shape>,
29 },
30
31 /// A field was not initialized during build
32 UninitializedField {
33 /// The shape containing the field
34 shape: &'shape Shape<'shape>,
35 /// The name of the field that wasn't initialized
36 field_name: &'shape str,
37 },
38
39 /// A field in an enum variant was not initialized during build
40 UninitializedEnumField {
41 /// The enum shape
42 shape: &'shape Shape<'shape>,
43 /// The name of the field that wasn't initialized
44 field_name: &'shape str,
45 /// The name of the variant containing the field
46 variant_name: &'shape str,
47 },
48
49 /// A scalar value was not initialized during build
50 UninitializedValue {
51 /// The scalar shape
52 shape: &'shape Shape<'shape>,
53 },
54
55 /// An invariant of the reflection system was violated.
56 InvariantViolation {
57 /// The invariant that was violated.
58 invariant: &'shape str,
59 },
60
61 /// Attempted to set a value to its default, but the value doesn't implement `Default`.
62 MissingCharacteristic {
63 /// The shape of the value that doesn't implement `Default`.
64 shape: &'shape Shape<'shape>,
65 /// The characteristic that is missing.
66 characteristic: Characteristic,
67 },
68
69 /// An operation failed for a given shape
70 OperationFailed {
71 /// The shape of the value for which the operation failed.
72 shape: &'shape Shape<'shape>,
73 /// The name of the operation that failed.
74 operation: &'shape str,
75 },
76
77 /// An error occurred when attempting to access or modify a field.
78 FieldError {
79 /// The shape of the value containing the field.
80 shape: &'shape Shape<'shape>,
81 /// The specific error that occurred with the field.
82 field_error: FieldError,
83 },
84
85 /// Indicates that we try to access a field on an `Arc<T>`, for example, and the field might exist
86 /// on the T, but you need to do begin_smart_ptr first when using the WIP API.
87 MissingPushPointee {
88 /// The smart pointer (`Arc<T>`, `Box<T>` etc.) shape on which field was caleld
89 shape: &'shape Shape<'shape>,
90 },
91
92 /// An unknown error occurred.
93 Unknown,
94
95 /// An error occured while putting
96 TryFromError {
97 /// The shape of the value being converted from.
98 src_shape: &'shape Shape<'shape>,
99
100 /// The shape of the value being converted to.
101 dst_shape: &'shape Shape<'shape>,
102
103 /// The inner error
104 inner: TryFromError<'shape>,
105 },
106
107 /// A shape has a `default` attribute, but no implementation of the `Default` trait.
108 DefaultAttrButNoDefaultImpl {
109 /// The shape of the value that has a `default` attribute but no default implementation.
110 shape: &'shape Shape<'shape>,
111 },
112
113 /// The type is unsized
114 Unsized {
115 /// The shape for the type that is unsized
116 shape: &'shape Shape<'shape>,
117 /// The operation we were trying to perform
118 operation: &'static str,
119 },
120
121 /// Array not fully initialized during build
122 ArrayNotFullyInitialized {
123 /// The shape of the array
124 shape: &'shape Shape<'shape>,
125 /// The number of elements pushed
126 pushed_count: usize,
127 /// The expected array size
128 expected_size: usize,
129 },
130
131 /// Array index out of bounds
132 ArrayIndexOutOfBounds {
133 /// The shape of the array
134 shape: &'shape Shape<'shape>,
135 /// The index that was out of bounds
136 index: usize,
137 /// The array size
138 size: usize,
139 },
140
141 /// Invalid operation for the current state
142 InvalidOperation {
143 /// The operation that was attempted
144 operation: &'static str,
145 /// The reason why it failed
146 reason: &'static str,
147 },
148
149 /// No active frame in Partial
150 NoActiveFrame,
151}
152
153impl core::fmt::Display for ReflectError<'_> {
154 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
155 match self {
156 ReflectError::NoSuchVariant { enum_type } => {
157 write!(f, "No such variant in enum. Known variants: ")?;
158 for v in enum_type.variants {
159 write!(f, ", {}", v.name.cyan())?;
160 }
161 write!(f, ", that's it.")
162 }
163 ReflectError::WrongShape { expected, actual } => {
164 write!(
165 f,
166 "Wrong shape: expected {}, but got {}",
167 expected.green(),
168 actual.red()
169 )
170 }
171 ReflectError::WasNotA { expected, actual } => {
172 write!(
173 f,
174 "Wrong shape: expected {}, but got {}",
175 expected.green(),
176 actual.red()
177 )
178 }
179 ReflectError::UninitializedField { shape, field_name } => {
180 write!(f, "Field '{shape}::{field_name}' was not initialized")
181 }
182 ReflectError::UninitializedEnumField {
183 shape,
184 field_name,
185 variant_name,
186 } => {
187 write!(
188 f,
189 "Field '{}::{}' in variant '{}' was not initialized",
190 shape.blue(),
191 field_name.yellow(),
192 variant_name.red()
193 )
194 }
195 ReflectError::UninitializedValue { shape } => {
196 write!(f, "Value '{}' was not initialized", shape.blue())
197 }
198 ReflectError::InvariantViolation { invariant } => {
199 write!(f, "Invariant violation: {}", invariant.red())
200 }
201 ReflectError::MissingCharacteristic {
202 shape,
203 characteristic,
204 } => write!(
205 f,
206 "{shape} does not implement characteristic {characteristic:?}",
207 ),
208 ReflectError::OperationFailed { shape, operation } => {
209 write!(
210 f,
211 "Operation failed on shape {}: {}",
212 shape.blue(),
213 operation
214 )
215 }
216 ReflectError::FieldError { shape, field_error } => {
217 write!(f, "Field error for shape {}: {}", shape.red(), field_error)
218 }
219 ReflectError::MissingPushPointee { shape } => {
220 write!(
221 f,
222 "Tried to access a field on smart pointer '{}', but you need to call {} first to work with the value it points to (and pop it with {} later)",
223 shape.blue(),
224 ".begin_smart_ptr()".yellow(),
225 ".pop()".yellow()
226 )
227 }
228 ReflectError::Unknown => write!(f, "Unknown error"),
229 ReflectError::TryFromError {
230 src_shape,
231 dst_shape,
232 inner,
233 } => {
234 write!(
235 f,
236 "While trying to put {} into a {}: {}",
237 src_shape.green(),
238 dst_shape.blue(),
239 inner.red()
240 )
241 }
242 ReflectError::DefaultAttrButNoDefaultImpl { shape } => write!(
243 f,
244 "Shape '{}' has a `default` attribute but no default implementation",
245 shape.red()
246 ),
247 ReflectError::Unsized { shape, operation } => write!(
248 f,
249 "Shape '{}' is unsized, can't perform operation {}",
250 shape.red(),
251 operation
252 ),
253 ReflectError::ArrayNotFullyInitialized {
254 shape,
255 pushed_count,
256 expected_size,
257 } => {
258 write!(
259 f,
260 "Array '{}' not fully initialized: expected {} elements, but got {}",
261 shape.blue(),
262 expected_size,
263 pushed_count
264 )
265 }
266 ReflectError::ArrayIndexOutOfBounds { shape, index, size } => {
267 write!(
268 f,
269 "Array index {} out of bounds for '{}' (array length is {})",
270 index,
271 shape.blue(),
272 size
273 )
274 }
275 ReflectError::InvalidOperation { operation, reason } => {
276 write!(f, "Invalid operation '{}': {}", operation.yellow(), reason)
277 }
278 ReflectError::NoActiveFrame => {
279 write!(f, "No active frame in Partial")
280 }
281 }
282 }
283}
284
285impl core::fmt::Debug for ReflectError<'_> {
286 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
287 // Use Display implementation for more readable output
288 write!(f, "ReflectError({self})")
289 }
290}
291
292impl core::error::Error for ReflectError<'_> {}