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