Skip to content

Commit

Permalink
Make visit_clobber panic-safe.
Browse files Browse the repository at this point in the history
  • Loading branch information
nnethercote committed Feb 26, 2019
1 parent f47ec2a commit eddd07c
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/libsyntax/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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`.
Expand Down

0 comments on commit eddd07c

Please sign in to comment.