facet_reflect/
error.rs

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