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