1 | #![doc = include_str!("error.md" )] |
2 | #![unstable (feature = "error_in_core" , issue = "103765" )] |
3 | |
4 | #[cfg (test)] |
5 | mod tests; |
6 | |
7 | use crate::any::TypeId; |
8 | use crate::fmt::{Debug, Display, Formatter, Result}; |
9 | |
10 | /// `Error` is a trait representing the basic expectations for error values, |
11 | /// i.e., values of type `E` in [`Result<T, E>`]. |
12 | /// |
13 | /// Errors must describe themselves through the [`Display`] and [`Debug`] |
14 | /// traits. Error messages are typically concise lowercase sentences without |
15 | /// trailing punctuation: |
16 | /// |
17 | /// ``` |
18 | /// let err = "NaN" .parse::<u32>().unwrap_err(); |
19 | /// assert_eq!(err.to_string(), "invalid digit found in string" ); |
20 | /// ``` |
21 | /// |
22 | /// Errors may provide cause information. [`Error::source()`] is generally |
23 | /// used when errors cross "abstraction boundaries". If one module must report |
24 | /// an error that is caused by an error from a lower-level module, it can allow |
25 | /// accessing that error via [`Error::source()`]. This makes it possible for the |
26 | /// high-level module to provide its own errors while also revealing some of the |
27 | /// implementation for debugging. |
28 | #[stable (feature = "rust1" , since = "1.0.0" )] |
29 | #[cfg_attr (not(test), rustc_diagnostic_item = "Error" )] |
30 | #[rustc_has_incoherent_inherent_impls ] |
31 | #[allow (multiple_supertrait_upcastable)] |
32 | pub trait Error: Debug + Display { |
33 | /// The lower-level source of this error, if any. |
34 | /// |
35 | /// # Examples |
36 | /// |
37 | /// ``` |
38 | /// use std::error::Error; |
39 | /// use std::fmt; |
40 | /// |
41 | /// #[derive(Debug)] |
42 | /// struct SuperError { |
43 | /// source: SuperErrorSideKick, |
44 | /// } |
45 | /// |
46 | /// impl fmt::Display for SuperError { |
47 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
48 | /// write!(f, "SuperError is here!" ) |
49 | /// } |
50 | /// } |
51 | /// |
52 | /// impl Error for SuperError { |
53 | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
54 | /// Some(&self.source) |
55 | /// } |
56 | /// } |
57 | /// |
58 | /// #[derive(Debug)] |
59 | /// struct SuperErrorSideKick; |
60 | /// |
61 | /// impl fmt::Display for SuperErrorSideKick { |
62 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
63 | /// write!(f, "SuperErrorSideKick is here!" ) |
64 | /// } |
65 | /// } |
66 | /// |
67 | /// impl Error for SuperErrorSideKick {} |
68 | /// |
69 | /// fn get_super_error() -> Result<(), SuperError> { |
70 | /// Err(SuperError { source: SuperErrorSideKick }) |
71 | /// } |
72 | /// |
73 | /// fn main() { |
74 | /// match get_super_error() { |
75 | /// Err(e) => { |
76 | /// println!("Error: {e}" ); |
77 | /// println!("Caused by: {}" , e.source().unwrap()); |
78 | /// } |
79 | /// _ => println!("No error" ), |
80 | /// } |
81 | /// } |
82 | /// ``` |
83 | #[stable (feature = "error_source" , since = "1.30.0" )] |
84 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
85 | None |
86 | } |
87 | |
88 | /// Gets the `TypeId` of `self`. |
89 | #[doc (hidden)] |
90 | #[unstable ( |
91 | feature = "error_type_id" , |
92 | reason = "this is memory-unsafe to override in user code" , |
93 | issue = "60784" |
94 | )] |
95 | fn type_id(&self, _: private::Internal) -> TypeId |
96 | where |
97 | Self: 'static, |
98 | { |
99 | TypeId::of::<Self>() |
100 | } |
101 | |
102 | /// ``` |
103 | /// if let Err(e) = "xc" .parse::<u32>() { |
104 | /// // Print `e` itself, no need for description(). |
105 | /// eprintln!("Error: {e}" ); |
106 | /// } |
107 | /// ``` |
108 | #[stable (feature = "rust1" , since = "1.0.0" )] |
109 | #[deprecated (since = "1.42.0" , note = "use the Display impl or to_string()" )] |
110 | fn description(&self) -> &str { |
111 | "description() is deprecated; use Display" |
112 | } |
113 | |
114 | #[stable (feature = "rust1" , since = "1.0.0" )] |
115 | #[deprecated ( |
116 | since = "1.33.0" , |
117 | note = "replaced by Error::source, which can support downcasting" |
118 | )] |
119 | #[allow (missing_docs)] |
120 | fn cause(&self) -> Option<&dyn Error> { |
121 | self.source() |
122 | } |
123 | |
124 | /// Provides type based access to context intended for error reports. |
125 | /// |
126 | /// Used in conjunction with [`Request::provide_value`] and [`Request::provide_ref`] to extract |
127 | /// references to member variables from `dyn Error` trait objects. |
128 | /// |
129 | /// # Example |
130 | /// |
131 | /// ```rust |
132 | /// #![feature(error_generic_member_access)] |
133 | /// #![feature(error_in_core)] |
134 | /// use core::fmt; |
135 | /// use core::error::{request_ref, Request}; |
136 | /// |
137 | /// #[derive(Debug)] |
138 | /// enum MyLittleTeaPot { |
139 | /// Empty, |
140 | /// } |
141 | /// |
142 | /// #[derive(Debug)] |
143 | /// struct MyBacktrace { |
144 | /// // ... |
145 | /// } |
146 | /// |
147 | /// impl MyBacktrace { |
148 | /// fn new() -> MyBacktrace { |
149 | /// // ... |
150 | /// # MyBacktrace {} |
151 | /// } |
152 | /// } |
153 | /// |
154 | /// #[derive(Debug)] |
155 | /// struct Error { |
156 | /// backtrace: MyBacktrace, |
157 | /// } |
158 | /// |
159 | /// impl fmt::Display for Error { |
160 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
161 | /// write!(f, "Example Error" ) |
162 | /// } |
163 | /// } |
164 | /// |
165 | /// impl std::error::Error for Error { |
166 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
167 | /// request |
168 | /// .provide_ref::<MyBacktrace>(&self.backtrace); |
169 | /// } |
170 | /// } |
171 | /// |
172 | /// fn main() { |
173 | /// let backtrace = MyBacktrace::new(); |
174 | /// let error = Error { backtrace }; |
175 | /// let dyn_error = &error as &dyn std::error::Error; |
176 | /// let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap(); |
177 | /// |
178 | /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); |
179 | /// assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none()); |
180 | /// } |
181 | /// ``` |
182 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
183 | #[allow (unused_variables)] |
184 | fn provide<'a>(&'a self, request: &mut Request<'a>) {} |
185 | } |
186 | mod private { |
187 | // This is a hack to prevent `type_id` from being overridden by `Error` |
188 | // implementations, since that can enable unsound downcasting. |
189 | #[unstable (feature = "error_type_id" , issue = "60784" )] |
190 | #[derive (Debug)] |
191 | pub struct Internal; |
192 | } |
193 | |
194 | #[unstable (feature = "never_type" , issue = "35121" )] |
195 | impl Error for ! {} |
196 | |
197 | // Copied from `any.rs`. |
198 | impl dyn Error + 'static { |
199 | /// Returns `true` if the inner type is the same as `T`. |
200 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
201 | #[inline ] |
202 | pub fn is<T: Error + 'static>(&self) -> bool { |
203 | // Get `TypeId` of the type this function is instantiated with. |
204 | let t = TypeId::of::<T>(); |
205 | |
206 | // Get `TypeId` of the type in the trait object (`self`). |
207 | let concrete = self.type_id(private::Internal); |
208 | |
209 | // Compare both `TypeId`s on equality. |
210 | t == concrete |
211 | } |
212 | |
213 | /// Returns some reference to the inner value if it is of type `T`, or |
214 | /// `None` if it isn't. |
215 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
216 | #[inline ] |
217 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
218 | if self.is::<T>() { |
219 | // SAFETY: `is` ensures this type cast is correct |
220 | unsafe { Some(&*(self as *const dyn Error as *const T)) } |
221 | } else { |
222 | None |
223 | } |
224 | } |
225 | |
226 | /// Returns some mutable reference to the inner value if it is of type `T`, or |
227 | /// `None` if it isn't. |
228 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
229 | #[inline ] |
230 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
231 | if self.is::<T>() { |
232 | // SAFETY: `is` ensures this type cast is correct |
233 | unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } |
234 | } else { |
235 | None |
236 | } |
237 | } |
238 | } |
239 | |
240 | impl dyn Error + 'static + Send { |
241 | /// Forwards to the method defined on the type `dyn Error`. |
242 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
243 | #[inline ] |
244 | pub fn is<T: Error + 'static>(&self) -> bool { |
245 | <dyn Error + 'static>::is::<T>(self) |
246 | } |
247 | |
248 | /// Forwards to the method defined on the type `dyn Error`. |
249 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
250 | #[inline ] |
251 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
252 | <dyn Error + 'static>::downcast_ref::<T>(self) |
253 | } |
254 | |
255 | /// Forwards to the method defined on the type `dyn Error`. |
256 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
257 | #[inline ] |
258 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
259 | <dyn Error + 'static>::downcast_mut::<T>(self) |
260 | } |
261 | } |
262 | |
263 | impl dyn Error + 'static + Send + Sync { |
264 | /// Forwards to the method defined on the type `dyn Error`. |
265 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
266 | #[inline ] |
267 | pub fn is<T: Error + 'static>(&self) -> bool { |
268 | <dyn Error + 'static>::is::<T>(self) |
269 | } |
270 | |
271 | /// Forwards to the method defined on the type `dyn Error`. |
272 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
273 | #[inline ] |
274 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
275 | <dyn Error + 'static>::downcast_ref::<T>(self) |
276 | } |
277 | |
278 | /// Forwards to the method defined on the type `dyn Error`. |
279 | #[stable (feature = "error_downcast" , since = "1.3.0" )] |
280 | #[inline ] |
281 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
282 | <dyn Error + 'static>::downcast_mut::<T>(self) |
283 | } |
284 | } |
285 | |
286 | impl dyn Error { |
287 | /// Returns an iterator starting with the current error and continuing with |
288 | /// recursively calling [`Error::source`]. |
289 | /// |
290 | /// If you want to omit the current error and only use its sources, |
291 | /// use `skip(1)`. |
292 | /// |
293 | /// # Examples |
294 | /// |
295 | /// ``` |
296 | /// #![feature(error_iter)] |
297 | /// use std::error::Error; |
298 | /// use std::fmt; |
299 | /// |
300 | /// #[derive(Debug)] |
301 | /// struct A; |
302 | /// |
303 | /// #[derive(Debug)] |
304 | /// struct B(Option<Box<dyn Error + 'static>>); |
305 | /// |
306 | /// impl fmt::Display for A { |
307 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
308 | /// write!(f, "A" ) |
309 | /// } |
310 | /// } |
311 | /// |
312 | /// impl fmt::Display for B { |
313 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
314 | /// write!(f, "B" ) |
315 | /// } |
316 | /// } |
317 | /// |
318 | /// impl Error for A {} |
319 | /// |
320 | /// impl Error for B { |
321 | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
322 | /// self.0.as_ref().map(|e| e.as_ref()) |
323 | /// } |
324 | /// } |
325 | /// |
326 | /// let b = B(Some(Box::new(A))); |
327 | /// |
328 | /// // let err : Box<Error> = b.into(); // or |
329 | /// let err = &b as &(dyn Error); |
330 | /// |
331 | /// let mut iter = err.sources(); |
332 | /// |
333 | /// assert_eq!("B" .to_string(), iter.next().unwrap().to_string()); |
334 | /// assert_eq!("A" .to_string(), iter.next().unwrap().to_string()); |
335 | /// assert!(iter.next().is_none()); |
336 | /// assert!(iter.next().is_none()); |
337 | /// ``` |
338 | #[unstable (feature = "error_iter" , issue = "58520" )] |
339 | #[inline ] |
340 | pub fn sources(&self) -> Source<'_> { |
341 | // You may think this method would be better in the Error trait, and you'd be right. |
342 | // Unfortunately that doesn't work, not because of the object safety rules but because we |
343 | // save a reference to self in Sources below as a trait object. If this method was |
344 | // declared in Error, then self would have the type &T where T is some concrete type which |
345 | // implements Error. We would need to coerce self to have type &dyn Error, but that requires |
346 | // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error |
347 | // since that would forbid Error trait objects, and we can't put that bound on the method |
348 | // because that means the method can't be called on trait objects (we'd also need the |
349 | // 'static bound, but that isn't allowed because methods with bounds on Self other than |
350 | // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. |
351 | |
352 | Source { current: Some(self) } |
353 | } |
354 | } |
355 | |
356 | /// Request a value of type `T` from the given `impl Error`. |
357 | /// |
358 | /// # Examples |
359 | /// |
360 | /// Get a string value from an error. |
361 | /// |
362 | /// ```rust |
363 | /// # #![feature (error_generic_member_access)] |
364 | /// # #![feature (error_in_core)] |
365 | /// use std::error::Error; |
366 | /// use core::error::request_value; |
367 | /// |
368 | /// fn get_string(err: &impl Error) -> String { |
369 | /// request_value::<String>(err).unwrap() |
370 | /// } |
371 | /// ``` |
372 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
373 | pub fn request_value<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<T> |
374 | where |
375 | T: 'static, |
376 | { |
377 | request_by_type_tag::<'a, tags::Value<T>>(err) |
378 | } |
379 | |
380 | /// Request a reference of type `T` from the given `impl Error`. |
381 | /// |
382 | /// # Examples |
383 | /// |
384 | /// Get a string reference from an error. |
385 | /// |
386 | /// ```rust |
387 | /// # #![feature (error_generic_member_access)] |
388 | /// # #![feature (error_in_core)] |
389 | /// use core::error::Error; |
390 | /// use core::error::request_ref; |
391 | /// |
392 | /// fn get_str(err: &impl Error) -> &str { |
393 | /// request_ref::<str>(err).unwrap() |
394 | /// } |
395 | /// ``` |
396 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
397 | pub fn request_ref<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<&'a T> |
398 | where |
399 | T: 'static + ?Sized, |
400 | { |
401 | request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(err) |
402 | } |
403 | |
404 | /// Request a specific value by tag from the `Error`. |
405 | fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reified> |
406 | where |
407 | I: tags::Type<'a>, |
408 | { |
409 | let mut tagged: TaggedOption<'_, I> = TaggedOption::<'a, I>(None); |
410 | err.provide(tagged.as_request()); |
411 | tagged.0 |
412 | } |
413 | |
414 | /////////////////////////////////////////////////////////////////////////////// |
415 | // Request and its methods |
416 | /////////////////////////////////////////////////////////////////////////////// |
417 | |
418 | /// `Request` supports generic, type-driven access to data. Its use is currently restricted to the |
419 | /// standard library in cases where trait authors wish to allow trait implementors to share generic |
420 | /// information across trait boundaries. The motivating and prototypical use case is |
421 | /// `core::error::Error` which would otherwise require a method per concrete type (eg. |
422 | /// `std::backtrace::Backtrace` instance that implementors want to expose to users). |
423 | /// |
424 | /// # Data flow |
425 | /// |
426 | /// To describe the intended data flow for Request objects, let's consider two conceptual users |
427 | /// separated by API boundaries: |
428 | /// |
429 | /// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers |
430 | /// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`. |
431 | /// |
432 | /// * Producer - the producer provides objects when requested via Request; eg. a library with an |
433 | /// an `Error` implementation that automatically captures backtraces at the time instances are |
434 | /// created. |
435 | /// |
436 | /// The consumer only needs to know where to submit their request and are expected to handle the |
437 | /// request not being fulfilled by the use of `Option<T>` in the responses offered by the producer. |
438 | /// |
439 | /// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise |
440 | /// prepared to generate a value requested). eg, `backtrace::Backtrace` or |
441 | /// `std::backtrace::Backtrace` |
442 | /// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the |
443 | /// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and |
444 | /// `request_value` to simplify obtaining an `Option<T>` for a given type. |
445 | /// * The Producer, when requested, populates the given Request object which is given as a mutable |
446 | /// reference. |
447 | /// * The Consumer extracts a value or reference to the requested type from the `Request` object |
448 | /// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and ` |
449 | /// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at |
450 | /// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the |
451 | /// Producer cannot currently offer an instance of the requested type, not it can't or never will. |
452 | /// |
453 | /// # Examples |
454 | /// |
455 | /// The best way to demonstrate this is using an example implementation of `Error`'s `provide` trait |
456 | /// method: |
457 | /// |
458 | /// ``` |
459 | /// #![feature(error_generic_member_access)] |
460 | /// #![feature(error_in_core)] |
461 | /// use core::fmt; |
462 | /// use core::error::Request; |
463 | /// use core::error::request_ref; |
464 | /// |
465 | /// #[derive(Debug)] |
466 | /// enum MyLittleTeaPot { |
467 | /// Empty, |
468 | /// } |
469 | /// |
470 | /// #[derive(Debug)] |
471 | /// struct MyBacktrace { |
472 | /// // ... |
473 | /// } |
474 | /// |
475 | /// impl MyBacktrace { |
476 | /// fn new() -> MyBacktrace { |
477 | /// // ... |
478 | /// # MyBacktrace {} |
479 | /// } |
480 | /// } |
481 | /// |
482 | /// #[derive(Debug)] |
483 | /// struct Error { |
484 | /// backtrace: MyBacktrace, |
485 | /// } |
486 | /// |
487 | /// impl fmt::Display for Error { |
488 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
489 | /// write!(f, "Example Error" ) |
490 | /// } |
491 | /// } |
492 | /// |
493 | /// impl std::error::Error for Error { |
494 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
495 | /// request |
496 | /// .provide_ref::<MyBacktrace>(&self.backtrace); |
497 | /// } |
498 | /// } |
499 | /// |
500 | /// fn main() { |
501 | /// let backtrace = MyBacktrace::new(); |
502 | /// let error = Error { backtrace }; |
503 | /// let dyn_error = &error as &dyn std::error::Error; |
504 | /// let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap(); |
505 | /// |
506 | /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); |
507 | /// assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none()); |
508 | /// } |
509 | /// ``` |
510 | /// |
511 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
512 | #[cfg_attr (not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435 |
513 | pub struct Request<'a>(dyn Erased<'a> + 'a); |
514 | |
515 | impl<'a> Request<'a> { |
516 | /// Create a new `&mut Request` from a `&mut dyn Erased` trait object. |
517 | fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Request<'a> { |
518 | // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Request<'a>` is safe since |
519 | // `Request` is repr(transparent). |
520 | unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Request<'a>) } |
521 | } |
522 | |
523 | /// Provide a value or other type with only static lifetimes. |
524 | /// |
525 | /// # Examples |
526 | /// |
527 | /// Provides an `u8`. |
528 | /// |
529 | /// ```rust |
530 | /// #![feature(error_generic_member_access)] |
531 | /// #![feature(error_in_core)] |
532 | /// |
533 | /// use core::error::Request; |
534 | /// |
535 | /// #[derive(Debug)] |
536 | /// struct SomeConcreteType { field: u8 } |
537 | /// |
538 | /// impl std::fmt::Display for SomeConcreteType { |
539 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
540 | /// write!(f, "{} failed" , self.field) |
541 | /// } |
542 | /// } |
543 | /// |
544 | /// impl std::error::Error for SomeConcreteType { |
545 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
546 | /// request.provide_value::<u8>(self.field); |
547 | /// } |
548 | /// } |
549 | /// ``` |
550 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
551 | pub fn provide_value<T>(&mut self, value: T) -> &mut Self |
552 | where |
553 | T: 'static, |
554 | { |
555 | self.provide::<tags::Value<T>>(value) |
556 | } |
557 | |
558 | /// Provide a value or other type with only static lifetimes computed using a closure. |
559 | /// |
560 | /// # Examples |
561 | /// |
562 | /// Provides a `String` by cloning. |
563 | /// |
564 | /// ```rust |
565 | /// #![feature(error_generic_member_access)] |
566 | /// #![feature(error_in_core)] |
567 | /// |
568 | /// use core::error::Request; |
569 | /// |
570 | /// #[derive(Debug)] |
571 | /// struct SomeConcreteType { field: String } |
572 | /// |
573 | /// impl std::fmt::Display for SomeConcreteType { |
574 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
575 | /// write!(f, "{} failed" , self.field) |
576 | /// } |
577 | /// } |
578 | /// |
579 | /// impl std::error::Error for SomeConcreteType { |
580 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
581 | /// request.provide_value_with::<String>(|| self.field.clone()); |
582 | /// } |
583 | /// } |
584 | /// ``` |
585 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
586 | pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self |
587 | where |
588 | T: 'static, |
589 | { |
590 | self.provide_with::<tags::Value<T>>(fulfil) |
591 | } |
592 | |
593 | /// Provide a reference. The referee type must be bounded by `'static`, |
594 | /// but may be unsized. |
595 | /// |
596 | /// # Examples |
597 | /// |
598 | /// Provides a reference to a field as a `&str`. |
599 | /// |
600 | /// ```rust |
601 | /// #![feature(error_generic_member_access)] |
602 | /// #![feature(error_in_core)] |
603 | /// |
604 | /// use core::error::Request; |
605 | /// |
606 | /// #[derive(Debug)] |
607 | /// struct SomeConcreteType { field: String } |
608 | /// |
609 | /// impl std::fmt::Display for SomeConcreteType { |
610 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
611 | /// write!(f, "{} failed" , self.field) |
612 | /// } |
613 | /// } |
614 | /// |
615 | /// impl std::error::Error for SomeConcreteType { |
616 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
617 | /// request.provide_ref::<str>(&self.field); |
618 | /// } |
619 | /// } |
620 | /// ``` |
621 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
622 | pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self { |
623 | self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value) |
624 | } |
625 | |
626 | /// Provide a reference computed using a closure. The referee type |
627 | /// must be bounded by `'static`, but may be unsized. |
628 | /// |
629 | /// # Examples |
630 | /// |
631 | /// Provides a reference to a field as a `&str`. |
632 | /// |
633 | /// ```rust |
634 | /// #![feature(error_generic_member_access)] |
635 | /// #![feature(error_in_core)] |
636 | /// |
637 | /// use core::error::Request; |
638 | /// |
639 | /// #[derive(Debug)] |
640 | /// struct SomeConcreteType { business: String, party: String } |
641 | /// fn today_is_a_weekday() -> bool { true } |
642 | /// |
643 | /// impl std::fmt::Display for SomeConcreteType { |
644 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
645 | /// write!(f, "{} failed" , self.business) |
646 | /// } |
647 | /// } |
648 | /// |
649 | /// impl std::error::Error for SomeConcreteType { |
650 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
651 | /// request.provide_ref_with::<str>(|| { |
652 | /// if today_is_a_weekday() { |
653 | /// &self.business |
654 | /// } else { |
655 | /// &self.party |
656 | /// } |
657 | /// }); |
658 | /// } |
659 | /// } |
660 | /// ``` |
661 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
662 | pub fn provide_ref_with<T: ?Sized + 'static>( |
663 | &mut self, |
664 | fulfil: impl FnOnce() -> &'a T, |
665 | ) -> &mut Self { |
666 | self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil) |
667 | } |
668 | |
669 | /// Provide a value with the given `Type` tag. |
670 | fn provide<I>(&mut self, value: I::Reified) -> &mut Self |
671 | where |
672 | I: tags::Type<'a>, |
673 | { |
674 | if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { |
675 | res.0 = Some(value); |
676 | } |
677 | self |
678 | } |
679 | |
680 | /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work. |
681 | fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self |
682 | where |
683 | I: tags::Type<'a>, |
684 | { |
685 | if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { |
686 | res.0 = Some(fulfil()); |
687 | } |
688 | self |
689 | } |
690 | |
691 | /// Check if the `Request` would be satisfied if provided with a |
692 | /// value of the specified type. If the type does not match or has |
693 | /// already been provided, returns false. |
694 | /// |
695 | /// # Examples |
696 | /// |
697 | /// Check if an `u8` still needs to be provided and then provides |
698 | /// it. |
699 | /// |
700 | /// ```rust |
701 | /// #![feature(error_generic_member_access)] |
702 | /// #![feature(error_in_core)] |
703 | /// |
704 | /// use core::error::Request; |
705 | /// use core::error::request_value; |
706 | /// |
707 | /// #[derive(Debug)] |
708 | /// struct Parent(Option<u8>); |
709 | /// |
710 | /// impl std::fmt::Display for Parent { |
711 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
712 | /// write!(f, "a parent failed" ) |
713 | /// } |
714 | /// } |
715 | /// |
716 | /// impl std::error::Error for Parent { |
717 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
718 | /// if let Some(v) = self.0 { |
719 | /// request.provide_value::<u8>(v); |
720 | /// } |
721 | /// } |
722 | /// } |
723 | /// |
724 | /// #[derive(Debug)] |
725 | /// struct Child { |
726 | /// parent: Parent, |
727 | /// } |
728 | /// |
729 | /// impl Child { |
730 | /// // Pretend that this takes a lot of resources to evaluate. |
731 | /// fn an_expensive_computation(&self) -> Option<u8> { |
732 | /// Some(99) |
733 | /// } |
734 | /// } |
735 | /// |
736 | /// impl std::fmt::Display for Child { |
737 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
738 | /// write!(f, "child failed: \n because of parent: {}" , self.parent) |
739 | /// } |
740 | /// } |
741 | /// |
742 | /// impl std::error::Error for Child { |
743 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
744 | /// // In general, we don't know if this call will provide |
745 | /// // an `u8` value or not... |
746 | /// self.parent.provide(request); |
747 | /// |
748 | /// // ...so we check to see if the `u8` is needed before |
749 | /// // we run our expensive computation. |
750 | /// if request.would_be_satisfied_by_value_of::<u8>() { |
751 | /// if let Some(v) = self.an_expensive_computation() { |
752 | /// request.provide_value::<u8>(v); |
753 | /// } |
754 | /// } |
755 | /// |
756 | /// // The request will be satisfied now, regardless of if |
757 | /// // the parent provided the value or we did. |
758 | /// assert!(!request.would_be_satisfied_by_value_of::<u8>()); |
759 | /// } |
760 | /// } |
761 | /// |
762 | /// let parent = Parent(Some(42)); |
763 | /// let child = Child { parent }; |
764 | /// assert_eq!(Some(42), request_value::<u8>(&child)); |
765 | /// |
766 | /// let parent = Parent(None); |
767 | /// let child = Child { parent }; |
768 | /// assert_eq!(Some(99), request_value::<u8>(&child)); |
769 | /// |
770 | /// ``` |
771 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
772 | pub fn would_be_satisfied_by_value_of<T>(&self) -> bool |
773 | where |
774 | T: 'static, |
775 | { |
776 | self.would_be_satisfied_by::<tags::Value<T>>() |
777 | } |
778 | |
779 | /// Check if the `Request` would be satisfied if provided with a |
780 | /// reference to a value of the specified type. If the type does |
781 | /// not match or has already been provided, returns false. |
782 | /// |
783 | /// # Examples |
784 | /// |
785 | /// Check if a `&str` still needs to be provided and then provides |
786 | /// it. |
787 | /// |
788 | /// ```rust |
789 | /// #![feature(error_generic_member_access)] |
790 | /// #![feature(error_in_core)] |
791 | /// |
792 | /// use core::error::Request; |
793 | /// use core::error::request_ref; |
794 | /// |
795 | /// #[derive(Debug)] |
796 | /// struct Parent(Option<String>); |
797 | /// |
798 | /// impl std::fmt::Display for Parent { |
799 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
800 | /// write!(f, "a parent failed" ) |
801 | /// } |
802 | /// } |
803 | /// |
804 | /// impl std::error::Error for Parent { |
805 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
806 | /// if let Some(v) = &self.0 { |
807 | /// request.provide_ref::<str>(v); |
808 | /// } |
809 | /// } |
810 | /// } |
811 | /// |
812 | /// #[derive(Debug)] |
813 | /// struct Child { |
814 | /// parent: Parent, |
815 | /// name: String, |
816 | /// } |
817 | /// |
818 | /// impl Child { |
819 | /// // Pretend that this takes a lot of resources to evaluate. |
820 | /// fn an_expensive_computation(&self) -> Option<&str> { |
821 | /// Some(&self.name) |
822 | /// } |
823 | /// } |
824 | /// |
825 | /// impl std::fmt::Display for Child { |
826 | /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
827 | /// write!(f, "{} failed: \n {}" , self.name, self.parent) |
828 | /// } |
829 | /// } |
830 | /// |
831 | /// impl std::error::Error for Child { |
832 | /// fn provide<'a>(&'a self, request: &mut Request<'a>) { |
833 | /// // In general, we don't know if this call will provide |
834 | /// // a `str` reference or not... |
835 | /// self.parent.provide(request); |
836 | /// |
837 | /// // ...so we check to see if the `&str` is needed before |
838 | /// // we run our expensive computation. |
839 | /// if request.would_be_satisfied_by_ref_of::<str>() { |
840 | /// if let Some(v) = self.an_expensive_computation() { |
841 | /// request.provide_ref::<str>(v); |
842 | /// } |
843 | /// } |
844 | /// |
845 | /// // The request will be satisfied now, regardless of if |
846 | /// // the parent provided the reference or we did. |
847 | /// assert!(!request.would_be_satisfied_by_ref_of::<str>()); |
848 | /// } |
849 | /// } |
850 | /// |
851 | /// let parent = Parent(Some("parent" .into())); |
852 | /// let child = Child { parent, name: "child" .into() }; |
853 | /// assert_eq!(Some("parent" ), request_ref::<str>(&child)); |
854 | /// |
855 | /// let parent = Parent(None); |
856 | /// let child = Child { parent, name: "child" .into() }; |
857 | /// assert_eq!(Some("child" ), request_ref::<str>(&child)); |
858 | /// ``` |
859 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
860 | pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool |
861 | where |
862 | T: ?Sized + 'static, |
863 | { |
864 | self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>() |
865 | } |
866 | |
867 | fn would_be_satisfied_by<I>(&self) -> bool |
868 | where |
869 | I: tags::Type<'a>, |
870 | { |
871 | matches!(self.0.downcast::<I>(), Some(TaggedOption(None))) |
872 | } |
873 | } |
874 | |
875 | #[unstable (feature = "error_generic_member_access" , issue = "99301" )] |
876 | impl<'a> Debug for Request<'a> { |
877 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { |
878 | f.debug_struct(name:"Request" ).finish_non_exhaustive() |
879 | } |
880 | } |
881 | |
882 | /////////////////////////////////////////////////////////////////////////////// |
883 | // Type tags |
884 | /////////////////////////////////////////////////////////////////////////////// |
885 | |
886 | pub(crate) mod tags { |
887 | //! Type tags are used to identify a type using a separate value. This module includes type tags |
888 | //! for some very common types. |
889 | //! |
890 | //! Currently type tags are not exposed to the user. But in the future, if you want to use the |
891 | //! Request API with more complex types (typically those including lifetime parameters), you |
892 | //! will need to write your own tags. |
893 | |
894 | use crate::marker::PhantomData; |
895 | |
896 | /// This trait is implemented by specific tag types in order to allow |
897 | /// describing a type which can be requested for a given lifetime `'a`. |
898 | /// |
899 | /// A few example implementations for type-driven tags can be found in this |
900 | /// module, although crates may also implement their own tags for more |
901 | /// complex types with internal lifetimes. |
902 | pub(crate) trait Type<'a>: Sized + 'static { |
903 | /// The type of values which may be tagged by this tag for the given |
904 | /// lifetime. |
905 | type Reified: 'a; |
906 | } |
907 | |
908 | /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a |
909 | /// `?Sized` bound). E.g., `str`. |
910 | pub(crate) trait MaybeSizedType<'a>: Sized + 'static { |
911 | type Reified: 'a + ?Sized; |
912 | } |
913 | |
914 | impl<'a, T: Type<'a>> MaybeSizedType<'a> for T { |
915 | type Reified = T::Reified; |
916 | } |
917 | |
918 | /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements. |
919 | #[derive (Debug)] |
920 | pub(crate) struct Value<T: 'static>(PhantomData<T>); |
921 | |
922 | impl<'a, T: 'static> Type<'a> for Value<T> { |
923 | type Reified = T; |
924 | } |
925 | |
926 | /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound). |
927 | #[derive (Debug)] |
928 | pub(crate) struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>); |
929 | |
930 | impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> { |
931 | type Reified = T; |
932 | } |
933 | |
934 | /// Type-based tag for reference types (`&'a T`, where T is represented by |
935 | /// `<I as MaybeSizedType<'a>>::Reified`. |
936 | #[derive (Debug)] |
937 | pub(crate) struct Ref<I>(PhantomData<I>); |
938 | |
939 | impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> { |
940 | type Reified = &'a I::Reified; |
941 | } |
942 | } |
943 | |
944 | /// An `Option` with a type tag `I`. |
945 | /// |
946 | /// Since this struct implements `Erased`, the type can be erased to make a dynamically typed |
947 | /// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically |
948 | /// checked for the concrete type, there is some degree of type safety. |
949 | #[repr (transparent)] |
950 | pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>); |
951 | |
952 | impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> { |
953 | pub(crate) fn as_request(&mut self) -> &mut Request<'a> { |
954 | Request::new(self as &mut (dyn Erased<'a> + 'a)) |
955 | } |
956 | } |
957 | |
958 | /// Represents a type-erased but identifiable object. |
959 | /// |
960 | /// This trait is exclusively implemented by the `TaggedOption` type. |
961 | unsafe trait Erased<'a>: 'a { |
962 | /// The `TypeId` of the erased type. |
963 | fn tag_id(&self) -> TypeId; |
964 | } |
965 | |
966 | unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> { |
967 | fn tag_id(&self) -> TypeId { |
968 | TypeId::of::<I>() |
969 | } |
970 | } |
971 | |
972 | impl<'a> dyn Erased<'a> + 'a { |
973 | /// Returns some reference to the dynamic value if it is tagged with `I`, |
974 | /// or `None` otherwise. |
975 | #[inline ] |
976 | fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>> |
977 | where |
978 | I: tags::Type<'a>, |
979 | { |
980 | if self.tag_id() == TypeId::of::<I>() { |
981 | // SAFETY: Just checked whether we're pointing to an I. |
982 | Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() }) |
983 | } else { |
984 | None |
985 | } |
986 | } |
987 | |
988 | /// Returns some mutable reference to the dynamic value if it is tagged with `I`, |
989 | /// or `None` otherwise. |
990 | #[inline ] |
991 | fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>> |
992 | where |
993 | I: tags::Type<'a>, |
994 | { |
995 | if self.tag_id() == TypeId::of::<I>() { |
996 | // SAFETY: Just checked whether we're pointing to an I. |
997 | Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() }) |
998 | } else { |
999 | None |
1000 | } |
1001 | } |
1002 | } |
1003 | |
1004 | /// An iterator over an [`Error`] and its sources. |
1005 | /// |
1006 | /// If you want to omit the initial error and only process |
1007 | /// its sources, use `skip(1)`. |
1008 | #[unstable (feature = "error_iter" , issue = "58520" )] |
1009 | #[derive (Clone, Debug)] |
1010 | pub struct Source<'a> { |
1011 | current: Option<&'a (dyn Error + 'static)>, |
1012 | } |
1013 | |
1014 | #[unstable (feature = "error_iter" , issue = "58520" )] |
1015 | impl<'a> Iterator for Source<'a> { |
1016 | type Item = &'a (dyn Error + 'static); |
1017 | |
1018 | fn next(&mut self) -> Option<Self::Item> { |
1019 | let current: Option<&dyn Error> = self.current; |
1020 | self.current = self.current.and_then(Error::source); |
1021 | current |
1022 | } |
1023 | } |
1024 | |
1025 | #[stable (feature = "error_by_ref" , since = "1.51.0" )] |
1026 | impl<'a, T: Error + ?Sized> Error for &'a T { |
1027 | #[allow (deprecated, deprecated_in_future)] |
1028 | fn description(&self) -> &str { |
1029 | Error::description(&**self) |
1030 | } |
1031 | |
1032 | #[allow (deprecated)] |
1033 | fn cause(&self) -> Option<&dyn Error> { |
1034 | Error::cause(&**self) |
1035 | } |
1036 | |
1037 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
1038 | Error::source(&**self) |
1039 | } |
1040 | |
1041 | fn provide<'b>(&'b self, request: &mut Request<'b>) { |
1042 | Error::provide(&**self, request); |
1043 | } |
1044 | } |
1045 | |
1046 | #[stable (feature = "fmt_error" , since = "1.11.0" )] |
1047 | impl Error for crate::fmt::Error { |
1048 | #[allow (deprecated)] |
1049 | fn description(&self) -> &str { |
1050 | "an error occurred when formatting an argument" |
1051 | } |
1052 | } |
1053 | |
1054 | #[stable (feature = "try_borrow" , since = "1.13.0" )] |
1055 | impl Error for crate::cell::BorrowError { |
1056 | #[allow (deprecated)] |
1057 | fn description(&self) -> &str { |
1058 | "already mutably borrowed" |
1059 | } |
1060 | } |
1061 | |
1062 | #[stable (feature = "try_borrow" , since = "1.13.0" )] |
1063 | impl Error for crate::cell::BorrowMutError { |
1064 | #[allow (deprecated)] |
1065 | fn description(&self) -> &str { |
1066 | "already borrowed" |
1067 | } |
1068 | } |
1069 | |
1070 | #[stable (feature = "try_from" , since = "1.34.0" )] |
1071 | impl Error for crate::char::CharTryFromError { |
1072 | #[allow (deprecated)] |
1073 | fn description(&self) -> &str { |
1074 | "converted integer out of range for `char`" |
1075 | } |
1076 | } |
1077 | |
1078 | #[stable (feature = "duration_checked_float" , since = "1.66.0" )] |
1079 | impl Error for crate::time::TryFromFloatSecsError {} |
1080 | |
1081 | #[stable (feature = "cstr_from_bytes_until_nul" , since = "1.69.0" )] |
1082 | impl Error for crate::ffi::FromBytesUntilNulError {} |
1083 | |
1084 | #[unstable (feature = "get_many_mut" , issue = "104642" )] |
1085 | impl<const N: usize> Error for crate::slice::GetManyMutError<N> {} |
1086 | |