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