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(Debug, 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    /// An enum had no variant selected during build
51    NoVariantSelected {
52        /// The enum shape
53        shape: &'shape Shape<'shape>,
54    },
55
56    /// A scalar value was not initialized during build
57    UninitializedValue {
58        /// The scalar shape
59        shape: &'shape Shape<'shape>,
60    },
61
62    /// An invariant of the reflection system was violated.
63    InvariantViolation {
64        /// The invariant that was violated.
65        invariant: &'shape str,
66    },
67
68    /// Attempted to set a value to its default, but the value doesn't implement `Default`.
69    MissingCharacteristic {
70        /// The shape of the value that doesn't implement `Default`.
71        shape: &'shape Shape<'shape>,
72        /// The characteristic that is missing.
73        characteristic: Characteristic,
74    },
75
76    /// An operation failed for a given shape
77    OperationFailed {
78        /// The shape of the value for which the operation failed.
79        shape: &'shape Shape<'shape>,
80        /// The name of the operation that failed.
81        operation: &'shape str,
82    },
83
84    /// An error occurred when attempting to access or modify a field.
85    FieldError {
86        /// The shape of the value containing the field.
87        shape: &'shape Shape<'shape>,
88        /// The specific error that occurred with the field.
89        field_error: FieldError,
90    },
91
92    /// Indicates that we try to access a field on an `Arc<T>`, for example, and the field might exist
93    /// on the T, but you need to do push_pointee first when using the WIP API.
94    MissingPushPointee {
95        /// The smart pointer (`Arc<T>`, `Box<T>` etc.) shape on which field was caleld
96        shape: &'shape Shape<'shape>,
97    },
98
99    /// An unknown error occurred.
100    Unknown,
101
102    /// An error occured while putting
103    TryFromError {
104        /// The shape of the value being converted from.
105        src_shape: &'shape Shape<'shape>,
106
107        /// The shape of the value being converted to.
108        dst_shape: &'shape Shape<'shape>,
109
110        /// The inner error
111        inner: TryFromError<'shape>,
112    },
113
114    /// A shape has a `default` attribute, but no implementation of the `Default` trait.
115    DefaultAttrButNoDefaultImpl {
116        /// The shape of the value that has a `default` attribute but no default implementation.
117        shape: &'shape Shape<'shape>,
118    },
119
120    /// The type is unsized
121    Unsized {
122        /// The shape for the type that is unsized
123        shape: &'shape Shape<'shape>,
124    },
125
126    /// Array not fully initialized during build
127    ArrayNotFullyInitialized {
128        /// The shape of the array
129        shape: &'shape Shape<'shape>,
130        /// The number of elements pushed
131        pushed_count: usize,
132        /// The expected array size
133        expected_size: usize,
134    },
135
136    /// Array index out of bounds
137    ArrayIndexOutOfBounds {
138        /// The shape of the array
139        shape: &'shape Shape<'shape>,
140        /// The index that was out of bounds
141        index: usize,
142        /// The array size
143        size: usize,
144    },
145}
146
147impl core::fmt::Display for ReflectError<'_> {
148    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149        match self {
150            ReflectError::NoSuchVariant { enum_type } => {
151                write!(f, "No such variant in enum. Known variants: ")?;
152                for v in enum_type.variants {
153                    write!(f, ", {}", v.name.cyan())?;
154                }
155                write!(f, ", that's it.")
156            }
157            ReflectError::WrongShape { expected, actual } => {
158                write!(
159                    f,
160                    "Wrong shape: expected {}, but got {}",
161                    expected.green(),
162                    actual.red()
163                )
164            }
165            ReflectError::WasNotA { expected, actual } => {
166                write!(
167                    f,
168                    "Wrong shape: expected {}, but got {}",
169                    expected.green(),
170                    actual.red()
171                )
172            }
173            ReflectError::UninitializedField { shape, field_name } => {
174                write!(f, "Field '{}::{}' was not initialized", shape, field_name)
175            }
176            ReflectError::UninitializedEnumField {
177                shape,
178                field_name,
179                variant_name,
180            } => {
181                write!(
182                    f,
183                    "Field '{}::{}' in variant '{}' was not initialized",
184                    shape.blue(),
185                    field_name.yellow(),
186                    variant_name.red()
187                )
188            }
189            ReflectError::NoVariantSelected { shape } => {
190                write!(f, "Enum '{}' had no variant selected", shape.blue())
191            }
192            ReflectError::UninitializedValue { shape } => {
193                write!(f, "Value '{}' was not initialized", shape.blue())
194            }
195            ReflectError::InvariantViolation { invariant } => {
196                write!(f, "Invariant violation: {}", invariant.red())
197            }
198            ReflectError::MissingCharacteristic {
199                shape,
200                characteristic,
201            } => write!(
202                f,
203                "{shape} does not implement characteristic {characteristic:?}",
204            ),
205            ReflectError::OperationFailed { shape, operation } => {
206                write!(
207                    f,
208                    "Operation failed on shape {}: {}",
209                    shape.blue(),
210                    operation
211                )
212            }
213            ReflectError::FieldError { shape, field_error } => {
214                write!(f, "Field error for shape {}: {}", shape.red(), field_error)
215            }
216            ReflectError::MissingPushPointee { shape } => {
217                write!(
218                    f,
219                    "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)",
220                    shape.blue(),
221                    ".push_pointee()".yellow(),
222                    ".pop()".yellow()
223                )
224            }
225            ReflectError::Unknown => write!(f, "Unknown error"),
226            ReflectError::TryFromError {
227                src_shape,
228                dst_shape,
229                inner,
230            } => {
231                write!(
232                    f,
233                    "While trying to put {} into a {}: {}",
234                    src_shape.green(),
235                    dst_shape.blue(),
236                    inner.red()
237                )
238            }
239            ReflectError::DefaultAttrButNoDefaultImpl { shape } => write!(
240                f,
241                "Shape '{}' has a `default` attribute but no default implementation",
242                shape.red()
243            ),
244            ReflectError::Unsized { shape } => write!(f, "Shape '{}' is unsized", shape.red()),
245            ReflectError::ArrayNotFullyInitialized {
246                shape,
247                pushed_count,
248                expected_size,
249            } => {
250                write!(
251                    f,
252                    "Array '{}' not fully initialized: expected {} elements, but got {}",
253                    shape.blue(),
254                    expected_size,
255                    pushed_count
256                )
257            }
258            ReflectError::ArrayIndexOutOfBounds { shape, index, size } => {
259                write!(
260                    f,
261                    "Array index {} out of bounds for '{}' (array length is {})",
262                    index,
263                    shape.blue(),
264                    size
265                )
266            }
267        }
268    }
269}
270
271impl core::error::Error for ReflectError<'_> {}