Skip to content

Commit c6a6053

Browse files
committed
Auto merge of rust-lang#32102 - alexcrichton:assert-safe-closures, r=aturon
std: Add impl of FnOnce to AssertRecoverSafe This was originally intended, but forgot to land by accident! cc rust-lang#27719
2 parents c9629d6 + ec58f40 commit c6a6053

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
#![feature(float_extras)]
231231
#![feature(float_from_str_radix)]
232232
#![feature(fnbox)]
233+
#![feature(fn_traits)]
233234
#![feature(heap_api)]
234235
#![feature(hashmap_hasher)]
235236
#![feature(inclusive_range)]

src/libstd/panic.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ pub trait RefRecoverSafe {}
129129
///
130130
/// # Examples
131131
///
132+
/// One way to use `AssertRecoverSafe` is to assert that the entire closure
133+
/// itself is recover safe, bypassing all checks for all variables:
134+
///
132135
/// ```
133136
/// #![feature(recover, std_panic)]
134137
///
@@ -144,10 +147,33 @@ pub trait RefRecoverSafe {}
144147
/// // });
145148
///
146149
/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
150+
/// let result = panic::recover(AssertRecoverSafe::new(|| {
151+
/// variable += 3;
152+
/// }));
153+
/// // ...
154+
/// ```
155+
///
156+
/// Wrapping the entire closure amounts to a blanket assertion that all captured
157+
/// variables are recover safe. This has the downside that if new captures are
158+
/// added in the future, they will also be considered recover safe. Therefore,
159+
/// you may prefer to just wrap individual captures, as shown below. This is
160+
/// more annotation, but it ensures that if a new capture is added which is not
161+
/// recover safe, you will get a compilation error at that time, which will
162+
/// allow you to consider whether that new capture in fact represent a bug or
163+
/// not.
164+
///
165+
/// ```
166+
/// #![feature(recover, std_panic)]
167+
///
168+
/// use std::panic::{self, AssertRecoverSafe};
169+
///
170+
/// let mut variable = 4;
171+
/// let other_capture = 3;
172+
///
147173
/// let result = {
148174
/// let mut wrapper = AssertRecoverSafe::new(&mut variable);
149175
/// panic::recover(move || {
150-
/// **wrapper += 3;
176+
/// **wrapper += other_capture;
151177
/// })
152178
/// };
153179
/// // ...
@@ -215,6 +241,14 @@ impl<T> DerefMut for AssertRecoverSafe<T> {
215241
}
216242
}
217243

244+
impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
245+
type Output = R;
246+
247+
extern "rust-call" fn call_once(self, _args: ()) -> R {
248+
(self.0)()
249+
}
250+
}
251+
218252
/// Invokes a closure, capturing the cause of panic if one occurs.
219253
///
220254
/// This function will return `Ok` with the closure's result if the closure

0 commit comments

Comments
 (0)