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