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"
77name = " failure"
88repository = " https://github.com/rust-lang-nursery/failure"
99version = " 0.1.2"
10+ build = " build.rs"
1011
1112[dependencies .failure_derive ]
1213optional = 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;
21use core:: ptr;
32
43use Fail ;
@@ -49,8 +48,23 @@ impl ErrorImpl {
4948 } ) ;
5049 match ret {
5150 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+
5468 Ok ( ret)
5569 }
5670 _ => Err ( self )
Original file line number Diff line number Diff line change @@ -122,6 +122,9 @@ impl Error {
122122 /// failure is of the type `T`. For this reason it returns a `Result` - in
123123 /// the case that the underlying error is of a different type, the
124124 /// 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" ) ) ]
125128 pub fn downcast < T : Fail > ( self ) -> Result < T , Error > {
126129 self . imp . downcast ( ) . map_err ( |imp| Error { imp } )
127130 }
@@ -225,4 +228,11 @@ mod test {
225228 drop ( error) ;
226229 assert ! ( true ) ;
227230 }
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+ }
228238}
You can’t perform that action at this time.
0 commit comments