File tree 1 file changed +10
-2
lines changed
1 file changed +10
-2
lines changed Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ use syntax_pos::Span;
21
21
22
22
use rustc_data_structures:: sync:: Lrc ;
23
23
use std:: ops:: DerefMut ;
24
+ use std:: { panic, process, ptr} ;
24
25
25
26
pub trait ExpectOne < A : Array > {
26
27
fn expect_one ( self , err : & ' static str ) -> A :: Item ;
@@ -305,11 +306,18 @@ pub trait MutVisitor: Sized {
305
306
306
307
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
307
308
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
308
- /// method.
309
+ /// method. Abort the program if the closure panics.
309
310
//
310
311
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
311
312
pub fn visit_clobber < T , F > ( t : & mut T , f : F ) where F : FnOnce ( T ) -> T {
312
- unsafe { std:: ptr:: write ( t, f ( std:: ptr:: read ( t) ) ) ; }
313
+ unsafe {
314
+ // Safe because `t` is used in a read-only fashion by `read()` before
315
+ // being overwritten by `write()`.
316
+ let old_t = ptr:: read ( t) ;
317
+ let new_t = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || f ( old_t) ) )
318
+ . unwrap_or_else ( |_| process:: abort ( ) ) ;
319
+ ptr:: write ( t, new_t) ;
320
+ }
313
321
}
314
322
315
323
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
You can’t perform that action at this time.
0 commit comments