47
47
// coherence challenge (e.g., specialization, neg impls, etc) we can
48
48
// reconsider what crate these items belong in.
49
49
50
- use boxed:: Box ;
50
+ use any:: TypeId ;
51
+ use boxed:: { self , Box } ;
51
52
use convert:: From ;
52
53
use fmt:: { self , Debug , Display } ;
53
- use marker:: { Send , Sync } ;
54
+ use marker:: { Send , Sync , Reflect } ;
55
+ use mem:: transmute;
54
56
use num;
55
- use option:: Option ;
56
- use option:: Option :: None ;
57
+ use option:: Option :: { self , Some , None } ;
58
+ use result:: Result :: { self , Ok , Err } ;
59
+ use raw:: TraitObject ;
57
60
use str;
58
61
use string:: { self , String } ;
59
62
60
63
/// Base functionality for all errors in Rust.
61
64
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
62
- pub trait Error : Debug + Display {
65
+ pub trait Error : Debug + Display + Reflect {
63
66
/// A short description of the error.
64
67
///
65
68
/// The description should not contain newlines or sentence-ending
@@ -71,6 +74,14 @@ pub trait Error: Debug + Display {
71
74
/// The lower-level cause of this error, if any.
72
75
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
73
76
fn cause ( & self ) -> Option < & Error > { None }
77
+
78
+ /// Get the `TypeId` of `self`
79
+ #[ doc( hidden) ]
80
+ #[ unstable( feature = "core" ,
81
+ reason = "unclear whether to commit to this public implementation detail" ) ]
82
+ fn type_id ( & self ) -> TypeId where Self : ' static {
83
+ TypeId :: of :: < Self > ( )
84
+ }
74
85
}
75
86
76
87
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -154,3 +165,112 @@ impl Error for string::FromUtf16Error {
154
165
}
155
166
}
156
167
168
+ // copied from any.rs
169
+ impl Error + ' static {
170
+ /// Returns true if the boxed type is the same as `T`
171
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
172
+ #[ inline]
173
+ pub fn is < T : Error + ' static > ( & self ) -> bool {
174
+ // Get TypeId of the type this function is instantiated with
175
+ let t = TypeId :: of :: < T > ( ) ;
176
+
177
+ // Get TypeId of the type in the trait object
178
+ let boxed = self . type_id ( ) ;
179
+
180
+ // Compare both TypeIds on equality
181
+ t == boxed
182
+ }
183
+
184
+ /// Returns some reference to the boxed value if it is of type `T`, or
185
+ /// `None` if it isn't.
186
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
187
+ #[ inline]
188
+ pub fn downcast_ref < T : Error + ' static > ( & self ) -> Option < & T > {
189
+ if self . is :: < T > ( ) {
190
+ unsafe {
191
+ // Get the raw representation of the trait object
192
+ let to: TraitObject = transmute ( self ) ;
193
+
194
+ // Extract the data pointer
195
+ Some ( transmute ( to. data ) )
196
+ }
197
+ } else {
198
+ None
199
+ }
200
+ }
201
+
202
+ /// Returns some mutable reference to the boxed value if it is of type `T`, or
203
+ /// `None` if it isn't.
204
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
205
+ #[ inline]
206
+ pub fn downcast_mut < T : Error + ' static > ( & mut self ) -> Option < & mut T > {
207
+ if self . is :: < T > ( ) {
208
+ unsafe {
209
+ // Get the raw representation of the trait object
210
+ let to: TraitObject = transmute ( self ) ;
211
+
212
+ // Extract the data pointer
213
+ Some ( transmute ( to. data ) )
214
+ }
215
+ } else {
216
+ None
217
+ }
218
+ }
219
+ }
220
+
221
+ impl Error + ' static + Send {
222
+ /// Forwards to the method defined on the type `Any`.
223
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
224
+ #[ inline]
225
+ pub fn is < T : Error + ' static > ( & self ) -> bool {
226
+ <Error + ' static >:: is :: < T > ( self )
227
+ }
228
+
229
+ /// Forwards to the method defined on the type `Any`.
230
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
231
+ #[ inline]
232
+ pub fn downcast_ref < T : Error + ' static > ( & self ) -> Option < & T > {
233
+ <Error + ' static >:: downcast_ref :: < T > ( self )
234
+ }
235
+
236
+ /// Forwards to the method defined on the type `Any`.
237
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
238
+ #[ inline]
239
+ pub fn downcast_mut < T : Error + ' static > ( & mut self ) -> Option < & mut T > {
240
+ <Error + ' static >:: downcast_mut :: < T > ( self )
241
+ }
242
+ }
243
+
244
+ impl Error {
245
+ #[ inline]
246
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
247
+ /// Attempt to downcast the box to a concrete type.
248
+ pub fn downcast < T : Error + ' static > ( self : Box < Self > ) -> Result < Box < T > , Box < Error > > {
249
+ if self . is :: < T > ( ) {
250
+ unsafe {
251
+ // Get the raw representation of the trait object
252
+ let raw = boxed:: into_raw ( self ) ;
253
+ let to: TraitObject =
254
+ transmute :: < * mut Error , TraitObject > ( raw) ;
255
+
256
+ // Extract the data pointer
257
+ Ok ( Box :: from_raw ( to. data as * mut T ) )
258
+ }
259
+ } else {
260
+ Err ( self )
261
+ }
262
+ }
263
+ }
264
+
265
+ impl Error + Send {
266
+ #[ inline]
267
+ #[ unstable( feature = "error_downcast" , reason = "recently added" ) ]
268
+ /// Attempt to downcast the box to a concrete type.
269
+ pub fn downcast < T : Error + ' static > ( self : Box < Self > ) -> Result < Box < T > , Box < Error + Send > > {
270
+ let err: Box < Error > = self ;
271
+ <Error >:: downcast ( err) . map_err ( |s| unsafe {
272
+ // reapply the Send marker
273
+ transmute :: < Box < Error > , Box < Error + Send > > ( s)
274
+ } )
275
+ }
276
+ }
0 commit comments