]>
Commit | Line | Data |
---|---|---|
f2b60f7d | 1 | #![doc = include_str!("error.md")] |
487cf647 | 2 | #![unstable(feature = "error_in_core", issue = "103765")] |
f2b60f7d FG |
3 | |
4 | #[cfg(test)] | |
5 | mod tests; | |
6 | ||
7 | use crate::any::{Demand, Provider, TypeId}; | |
8 | use crate::fmt::{Debug, Display}; | |
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] | |
353b0b11 | 31 | #[allow(multiple_supertrait_upcastable)] |
f2b60f7d FG |
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 [`Demand::provide_value`] and [`Demand::provide_ref`] to extract | |
127 | /// references to member variables from `dyn Error` trait objects. | |
128 | /// | |
129 | /// # Example | |
130 | /// | |
131 | /// ```rust | |
132 | /// #![feature(provide_any)] | |
133 | /// #![feature(error_generic_member_access)] | |
134 | /// use core::fmt; | |
135 | /// use core::any::Demand; | |
136 | /// | |
137 | /// #[derive(Debug)] | |
138 | /// struct MyBacktrace { | |
139 | /// // ... | |
140 | /// } | |
141 | /// | |
142 | /// impl MyBacktrace { | |
143 | /// fn new() -> MyBacktrace { | |
144 | /// // ... | |
145 | /// # MyBacktrace {} | |
146 | /// } | |
147 | /// } | |
148 | /// | |
149 | /// #[derive(Debug)] | |
150 | /// struct SourceError { | |
151 | /// // ... | |
152 | /// } | |
153 | /// | |
154 | /// impl fmt::Display for SourceError { | |
155 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
156 | /// write!(f, "Example Source Error") | |
157 | /// } | |
158 | /// } | |
159 | /// | |
160 | /// impl std::error::Error for SourceError {} | |
161 | /// | |
162 | /// #[derive(Debug)] | |
163 | /// struct Error { | |
164 | /// source: SourceError, | |
165 | /// backtrace: MyBacktrace, | |
166 | /// } | |
167 | /// | |
168 | /// impl fmt::Display for Error { | |
169 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
170 | /// write!(f, "Example Error") | |
171 | /// } | |
172 | /// } | |
173 | /// | |
174 | /// impl std::error::Error for Error { | |
175 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
176 | /// demand | |
177 | /// .provide_ref::<MyBacktrace>(&self.backtrace) | |
178 | /// .provide_ref::<dyn std::error::Error + 'static>(&self.source); | |
179 | /// } | |
180 | /// } | |
181 | /// | |
182 | /// fn main() { | |
183 | /// let backtrace = MyBacktrace::new(); | |
184 | /// let source = SourceError {}; | |
185 | /// let error = Error { source, backtrace }; | |
186 | /// let dyn_error = &error as &dyn std::error::Error; | |
187 | /// let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap(); | |
188 | /// | |
189 | /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); | |
190 | /// } | |
191 | /// ``` | |
192 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
193 | #[allow(unused_variables)] | |
194 | fn provide<'a>(&'a self, demand: &mut Demand<'a>) {} | |
195 | } | |
196 | ||
197 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
198 | impl<E> Provider for E | |
199 | where | |
200 | E: Error + ?Sized, | |
201 | { | |
202 | fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
203 | self.provide(demand) | |
204 | } | |
205 | } | |
206 | ||
207 | mod 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")] | |
216 | impl Error for ! {} | |
217 | ||
218 | impl<'a> dyn Error + 'a { | |
219 | /// Request a reference of type `T` as context about this error. | |
220 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
221 | pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> { | |
222 | core::any::request_ref(self) | |
223 | } | |
224 | ||
225 | /// Request a value of type `T` as context about this error. | |
226 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
227 | pub fn request_value<T: 'static>(&'a self) -> Option<T> { | |
228 | core::any::request_value(self) | |
229 | } | |
230 | } | |
231 | ||
232 | // Copied from `any.rs`. | |
233 | impl dyn Error + 'static { | |
234 | /// Returns `true` if the inner type is the same as `T`. | |
235 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
236 | #[inline] | |
237 | pub fn is<T: Error + 'static>(&self) -> bool { | |
238 | // Get `TypeId` of the type this function is instantiated with. | |
239 | let t = TypeId::of::<T>(); | |
240 | ||
241 | // Get `TypeId` of the type in the trait object (`self`). | |
242 | let concrete = self.type_id(private::Internal); | |
243 | ||
244 | // Compare both `TypeId`s on equality. | |
245 | t == concrete | |
246 | } | |
247 | ||
248 | /// Returns some reference to the inner value if it is of type `T`, or | |
249 | /// `None` if it isn't. | |
250 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
251 | #[inline] | |
252 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { | |
253 | if self.is::<T>() { | |
254 | // SAFETY: `is` ensures this type cast is correct | |
255 | unsafe { Some(&*(self as *const dyn Error as *const T)) } | |
256 | } else { | |
257 | None | |
258 | } | |
259 | } | |
260 | ||
261 | /// Returns some mutable reference to the inner value if it is of type `T`, or | |
262 | /// `None` if it isn't. | |
263 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
264 | #[inline] | |
265 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { | |
266 | if self.is::<T>() { | |
267 | // SAFETY: `is` ensures this type cast is correct | |
268 | unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } | |
269 | } else { | |
270 | None | |
271 | } | |
272 | } | |
273 | } | |
274 | ||
275 | impl dyn Error + 'static + Send { | |
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 is<T: Error + 'static>(&self) -> bool { | |
280 | <dyn Error + 'static>::is::<T>(self) | |
281 | } | |
282 | ||
283 | /// Forwards to the method defined on the type `dyn Error`. | |
284 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
285 | #[inline] | |
286 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { | |
287 | <dyn Error + 'static>::downcast_ref::<T>(self) | |
288 | } | |
289 | ||
290 | /// Forwards to the method defined on the type `dyn Error`. | |
291 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
292 | #[inline] | |
293 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { | |
294 | <dyn Error + 'static>::downcast_mut::<T>(self) | |
295 | } | |
296 | ||
297 | /// Request a reference of type `T` as context about this error. | |
298 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
299 | pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { | |
300 | <dyn Error>::request_ref(self) | |
301 | } | |
302 | ||
303 | /// Request a value of type `T` as context about this error. | |
304 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
305 | pub fn request_value<T: 'static>(&self) -> Option<T> { | |
306 | <dyn Error>::request_value(self) | |
307 | } | |
308 | } | |
309 | ||
310 | impl dyn Error + 'static + Send + Sync { | |
311 | /// Forwards to the method defined on the type `dyn Error`. | |
312 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
313 | #[inline] | |
314 | pub fn is<T: Error + 'static>(&self) -> bool { | |
315 | <dyn Error + 'static>::is::<T>(self) | |
316 | } | |
317 | ||
318 | /// Forwards to the method defined on the type `dyn Error`. | |
319 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
320 | #[inline] | |
321 | pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { | |
322 | <dyn Error + 'static>::downcast_ref::<T>(self) | |
323 | } | |
324 | ||
325 | /// Forwards to the method defined on the type `dyn Error`. | |
326 | #[stable(feature = "error_downcast", since = "1.3.0")] | |
327 | #[inline] | |
328 | pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { | |
329 | <dyn Error + 'static>::downcast_mut::<T>(self) | |
330 | } | |
331 | ||
332 | /// Request a reference of type `T` as context about this error. | |
333 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
334 | pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { | |
335 | <dyn Error>::request_ref(self) | |
336 | } | |
337 | ||
338 | /// Request a value of type `T` as context about this error. | |
339 | #[unstable(feature = "error_generic_member_access", issue = "99301")] | |
340 | pub fn request_value<T: 'static>(&self) -> Option<T> { | |
341 | <dyn Error>::request_value(self) | |
342 | } | |
343 | } | |
344 | ||
345 | impl dyn Error { | |
346 | /// Returns an iterator starting with the current error and continuing with | |
347 | /// recursively calling [`Error::source`]. | |
348 | /// | |
349 | /// If you want to omit the current error and only use its sources, | |
350 | /// use `skip(1)`. | |
351 | /// | |
352 | /// # Examples | |
353 | /// | |
354 | /// ``` | |
355 | /// #![feature(error_iter)] | |
356 | /// use std::error::Error; | |
357 | /// use std::fmt; | |
358 | /// | |
359 | /// #[derive(Debug)] | |
360 | /// struct A; | |
361 | /// | |
362 | /// #[derive(Debug)] | |
363 | /// struct B(Option<Box<dyn Error + 'static>>); | |
364 | /// | |
365 | /// impl fmt::Display for A { | |
366 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
367 | /// write!(f, "A") | |
368 | /// } | |
369 | /// } | |
370 | /// | |
371 | /// impl fmt::Display for B { | |
372 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
373 | /// write!(f, "B") | |
374 | /// } | |
375 | /// } | |
376 | /// | |
377 | /// impl Error for A {} | |
378 | /// | |
379 | /// impl Error for B { | |
380 | /// fn source(&self) -> Option<&(dyn Error + 'static)> { | |
381 | /// self.0.as_ref().map(|e| e.as_ref()) | |
382 | /// } | |
383 | /// } | |
384 | /// | |
385 | /// let b = B(Some(Box::new(A))); | |
386 | /// | |
387 | /// // let err : Box<Error> = b.into(); // or | |
388 | /// let err = &b as &(dyn Error); | |
389 | /// | |
390 | /// let mut iter = err.sources(); | |
391 | /// | |
392 | /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); | |
393 | /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); | |
394 | /// assert!(iter.next().is_none()); | |
395 | /// assert!(iter.next().is_none()); | |
396 | /// ``` | |
397 | #[unstable(feature = "error_iter", issue = "58520")] | |
398 | #[inline] | |
399 | pub fn sources(&self) -> Source<'_> { | |
400 | // You may think this method would be better in the Error trait, and you'd be right. | |
401 | // Unfortunately that doesn't work, not because of the object safety rules but because we | |
402 | // save a reference to self in Sources below as a trait object. If this method was | |
403 | // declared in Error, then self would have the type &T where T is some concrete type which | |
404 | // implements Error. We would need to coerce self to have type &dyn Error, but that requires | |
405 | // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error | |
406 | // since that would forbid Error trait objects, and we can't put that bound on the method | |
407 | // because that means the method can't be called on trait objects (we'd also need the | |
408 | // 'static bound, but that isn't allowed because methods with bounds on Self other than | |
409 | // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. | |
410 | ||
411 | Source { current: Some(self) } | |
412 | } | |
413 | } | |
414 | ||
415 | /// An iterator over an [`Error`] and its sources. | |
416 | /// | |
417 | /// If you want to omit the initial error and only process | |
418 | /// its sources, use `skip(1)`. | |
419 | #[unstable(feature = "error_iter", issue = "58520")] | |
420 | #[derive(Clone, Debug)] | |
421 | pub struct Source<'a> { | |
422 | current: Option<&'a (dyn Error + 'static)>, | |
423 | } | |
424 | ||
425 | #[unstable(feature = "error_iter", issue = "58520")] | |
426 | impl<'a> Iterator for Source<'a> { | |
427 | type Item = &'a (dyn Error + 'static); | |
428 | ||
429 | fn next(&mut self) -> Option<Self::Item> { | |
430 | let current = self.current; | |
431 | self.current = self.current.and_then(Error::source); | |
432 | current | |
433 | } | |
434 | } | |
435 | ||
436 | #[stable(feature = "error_by_ref", since = "1.51.0")] | |
437 | impl<'a, T: Error + ?Sized> Error for &'a T { | |
438 | #[allow(deprecated, deprecated_in_future)] | |
439 | fn description(&self) -> &str { | |
440 | Error::description(&**self) | |
441 | } | |
442 | ||
443 | #[allow(deprecated)] | |
444 | fn cause(&self) -> Option<&dyn Error> { | |
445 | Error::cause(&**self) | |
446 | } | |
447 | ||
448 | fn source(&self) -> Option<&(dyn Error + 'static)> { | |
449 | Error::source(&**self) | |
450 | } | |
451 | ||
452 | fn provide<'b>(&'b self, demand: &mut Demand<'b>) { | |
453 | Error::provide(&**self, demand); | |
454 | } | |
455 | } | |
456 | ||
457 | #[stable(feature = "fmt_error", since = "1.11.0")] | |
458 | impl Error for crate::fmt::Error { | |
459 | #[allow(deprecated)] | |
460 | fn description(&self) -> &str { | |
461 | "an error occurred when formatting an argument" | |
462 | } | |
463 | } | |
464 | ||
465 | #[stable(feature = "try_borrow", since = "1.13.0")] | |
466 | impl Error for crate::cell::BorrowError { | |
467 | #[allow(deprecated)] | |
468 | fn description(&self) -> &str { | |
469 | "already mutably borrowed" | |
470 | } | |
471 | } | |
472 | ||
473 | #[stable(feature = "try_borrow", since = "1.13.0")] | |
474 | impl Error for crate::cell::BorrowMutError { | |
475 | #[allow(deprecated)] | |
476 | fn description(&self) -> &str { | |
477 | "already borrowed" | |
478 | } | |
479 | } | |
480 | ||
481 | #[stable(feature = "try_from", since = "1.34.0")] | |
482 | impl Error for crate::char::CharTryFromError { | |
483 | #[allow(deprecated)] | |
484 | fn description(&self) -> &str { | |
485 | "converted integer out of range for `char`" | |
486 | } | |
487 | } | |
488 | ||
2b03887a FG |
489 | #[stable(feature = "duration_checked_float", since = "1.66.0")] |
490 | impl Error for crate::time::TryFromFloatSecsError {} | |
f2b60f7d | 491 | |
9ffffee4 | 492 | #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] |
f2b60f7d | 493 | impl Error for crate::ffi::FromBytesUntilNulError {} |
487cf647 FG |
494 | |
495 | #[unstable(feature = "get_many_mut", issue = "104642")] | |
496 | impl<const N: usize> Error for crate::slice::GetManyMutError<N> {} |