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