Rollup merge of #58630 - nnethercote:fix-fold_clobber, r=petrochenkov
Make `visit_clobber` panic-safe. Local measurements indicate the performance effect is negligible. r? @petrochenkov
This commit is contained in:
commit
a46b00eeb5
1 changed files with 10 additions and 2 deletions
|
@ -21,6 +21,7 @@ use syntax_pos::Span;
|
|||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::ops::DerefMut;
|
||||
use std::{panic, process, ptr};
|
||||
|
||||
pub trait ExpectOne<A: Array> {
|
||||
fn expect_one(self, err: &'static str) -> A::Item;
|
||||
|
@ -305,11 +306,18 @@ pub trait MutVisitor: Sized {
|
|||
|
||||
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
||||
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
|
||||
/// method.
|
||||
/// method. Abort the program if the closure panics.
|
||||
//
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
pub fn visit_clobber<T, F>(t: &mut T, f: F) where F: FnOnce(T) -> T {
|
||||
unsafe { std::ptr::write(t, f(std::ptr::read(t))); }
|
||||
unsafe {
|
||||
// Safe because `t` is used in a read-only fashion by `read()` before
|
||||
// being overwritten by `write()`.
|
||||
let old_t = ptr::read(t);
|
||||
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
|
||||
.unwrap_or_else(|_| process::abort());
|
||||
ptr::write(t, new_t);
|
||||
}
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
|
|
Loading…
Reference in a new issue