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<'_> {}