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