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    SmartPointerStr,
14    SmartPointerSlice,
15    Enum,
16    List,
17    Map,
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
180impl core::fmt::Display for ReflectError {
181    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182        match self {
183            ReflectError::NoSuchVariant { enum_type } => {
184                write!(f, "No such variant in enum. Known variants: ")?;
185                for v in enum_type.variants {
186                    write!(f, ", {}", v.name)?;
187                }
188                write!(f, ", that's it.")
189            }
190            ReflectError::WrongShape { expected, actual } => {
191                write!(f, "Wrong shape: expected {expected}, but got {actual}")
192            }
193            ReflectError::WasNotA { expected, actual } => {
194                write!(f, "Wrong shape: expected {expected}, but got {actual}")
195            }
196            ReflectError::UninitializedField { shape, field_name } => {
197                write!(f, "Field '{shape}::{field_name}' was not initialized")
198            }
199            ReflectError::UninitializedEnumField {
200                shape,
201                field_name,
202                variant_name,
203            } => {
204                write!(
205                    f,
206                    "Field '{shape}::{field_name}' in variant '{variant_name}' was not initialized"
207                )
208            }
209            ReflectError::UninitializedValue { shape } => {
210                write!(f, "Value '{shape}' was not initialized")
211            }
212            ReflectError::InvariantViolation { invariant } => {
213                write!(f, "Invariant violation: {invariant}")
214            }
215            ReflectError::MissingCharacteristic {
216                shape,
217                characteristic,
218            } => write!(
219                f,
220                "{shape} does not implement characteristic {characteristic:?}",
221            ),
222            ReflectError::OperationFailed { shape, operation } => {
223                write!(f, "Operation failed on shape {shape}: {operation}")
224            }
225            ReflectError::FieldError { shape, field_error } => {
226                write!(f, "Field error for shape {shape}: {field_error}")
227            }
228            ReflectError::MissingPushPointee { shape } => {
229                write!(
230                    f,
231                    "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)"
232                )
233            }
234            ReflectError::Unknown => write!(f, "Unknown error"),
235            ReflectError::TryFromError {
236                src_shape,
237                dst_shape,
238                inner,
239            } => {
240                write!(
241                    f,
242                    "While trying to put {src_shape} into a {dst_shape}: {inner}"
243                )
244            }
245            ReflectError::DefaultAttrButNoDefaultImpl { shape } => write!(
246                f,
247                "Shape '{shape}' has a `default` attribute but no default implementation"
248            ),
249            ReflectError::Unsized { shape, operation } => write!(
250                f,
251                "Shape '{shape}' is unsized, can't perform operation {operation}"
252            ),
253            ReflectError::ArrayNotFullyInitialized {
254                shape,
255                pushed_count,
256                expected_size,
257            } => {
258                write!(
259                    f,
260                    "Array '{shape}' not fully initialized: expected {expected_size} elements, but got {pushed_count}"
261                )
262            }
263            ReflectError::ArrayIndexOutOfBounds { shape, index, size } => {
264                write!(
265                    f,
266                    "Array index {index} out of bounds for '{shape}' (array length is {size})"
267                )
268            }
269            ReflectError::InvalidOperation { operation, reason } => {
270                write!(f, "Invalid operation '{operation}': {reason}")
271            }
272            ReflectError::UnexpectedTracker {
273                message,
274                current_tracker,
275            } => {
276                write!(f, "{message}: current tracker is {current_tracker:?}")
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 {}