This repository was archived by the owner on Aug 16, 2021. It is now read-only.
File tree Expand file tree Collapse file tree 4 files changed +67
-3
lines changed Expand file tree Collapse file tree 4 files changed +67
-3
lines changed Original file line number Diff line number Diff line change @@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0"
7
7
name = " failure"
8
8
repository = " https://github.com/rust-lang-nursery/failure"
9
9
version = " 0.1.2"
10
+ build = " build.rs"
10
11
11
12
[dependencies .failure_derive ]
12
13
optional = true
Original file line number Diff line number Diff line change
1
+ use std:: env;
2
+ use std:: process:: Command ;
3
+ use std:: str;
4
+ use std:: str:: FromStr ;
5
+
6
+ fn main ( ) {
7
+ if rustc_has_global_alloc ( ) {
8
+ println ! ( "cargo:rustc-cfg=has_global_alloc" ) ;
9
+ }
10
+ }
11
+
12
+ fn rustc_has_global_alloc ( ) -> bool {
13
+ let rustc = match env:: var_os ( "RUSTC" ) {
14
+ Some ( rustc) => rustc,
15
+ None => return false ,
16
+ } ;
17
+
18
+ let output = match Command :: new ( rustc) . arg ( "--version" ) . output ( ) {
19
+ Ok ( output) => output,
20
+ Err ( _) => return false ,
21
+ } ;
22
+
23
+ let version = match str:: from_utf8 ( & output. stdout ) {
24
+ Ok ( version) => version,
25
+ Err ( _) => return false ,
26
+ } ;
27
+
28
+ let mut pieces = version. split ( '.' ) ;
29
+ if pieces. next ( ) != Some ( "rustc 1" ) {
30
+ return true ;
31
+ }
32
+
33
+ let next = match pieces. next ( ) {
34
+ Some ( next) => next,
35
+ None => return false ,
36
+ } ;
37
+
38
+ u32:: from_str ( next) . unwrap_or ( 0 ) >= 28
39
+ }
Original file line number Diff line number Diff line change 1
- use core:: mem;
2
1
use core:: ptr;
3
2
4
3
use Fail ;
@@ -49,8 +48,23 @@ impl ErrorImpl {
49
48
} ) ;
50
49
match ret {
51
50
Some ( ret) => {
52
- // forget self (backtrace is dropped, failure is moved
53
- mem:: forget ( self ) ;
51
+ // deallocate the box without dropping the inner parts
52
+ #[ cfg( has_global_alloc) ] {
53
+ use std:: alloc:: { dealloc, Layout } ;
54
+ unsafe {
55
+ let layout = Layout :: for_value ( & * self . inner ) ;
56
+ let ptr = Box :: into_raw ( self . inner ) ;
57
+ dealloc ( ptr as * mut u8 , layout) ;
58
+ }
59
+ }
60
+
61
+ // slightly leaky versions of the above thing which makes the box
62
+ // itself leak. There is no good way around this as far as I know.
63
+ #[ cfg( not( has_global_alloc) ) ] {
64
+ use core:: mem;
65
+ mem:: forget ( self ) ;
66
+ }
67
+
54
68
Ok ( ret)
55
69
}
56
70
_ => Err ( self )
Original file line number Diff line number Diff line change @@ -122,6 +122,9 @@ impl Error {
122
122
/// failure is of the type `T`. For this reason it returns a `Result` - in
123
123
/// the case that the underlying error is of a different type, the
124
124
/// original `Error` is returned.
125
+ ///
126
+ /// Note that this method leaks on Rust versions < 1.28.0.
127
+ #[ cfg_attr( not( has_global_alloc) , deprecated( note = "this method leaks on Rust versions < 1.28" ) ) ]
125
128
pub fn downcast < T : Fail > ( self ) -> Result < T , Error > {
126
129
self . imp . downcast ( ) . map_err ( |imp| Error { imp } )
127
130
}
@@ -225,4 +228,11 @@ mod test {
225
228
drop ( error) ;
226
229
assert ! ( true ) ;
227
230
}
231
+
232
+ #[ test]
233
+ fn test_downcast ( ) {
234
+ let error: Error = io:: Error :: new ( io:: ErrorKind :: NotFound , "test" ) . into ( ) ;
235
+ let real_io_error = error. downcast_ref :: < io:: Error > ( ) . unwrap ( ) ;
236
+ assert_eq ! ( real_io_error. to_string( ) , "test" ) ;
237
+ }
228
238
}
You can’t perform that action at this time.
0 commit comments