Skip to content

Commit a9743e1

Browse files
authored
Rollup merge of #111875 - WaffleLapkin:defer_on_drop, r=Nilstrieb
Don't leak the function that is called on drop It probably wasn't causing problems anyway, but still, a `// this leaks, please don't pass anything that owns memory` is not sustainable. I could implement a version which does not require `Option`, but it would require `unsafe`, at which point it's probably not worth it.
2 parents 725cadb + e2b9530 commit a9743e1

File tree

5 files changed

+21
-15
lines changed

5 files changed

+21
-15
lines changed

compiler/rustc_data_structures/src/lib.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,27 @@ pub mod unord;
102102
pub use ena::undo_log;
103103
pub use ena::unify;
104104

105-
pub struct OnDrop<F: Fn()>(pub F);
105+
/// Returns a structure that calls `f` when dropped.
106+
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
107+
OnDrop(Some(f))
108+
}
109+
110+
pub struct OnDrop<F: FnOnce()>(Option<F>);
106111

107-
impl<F: Fn()> OnDrop<F> {
108-
/// Forgets the function which prevents it from running.
109-
/// Ensure that the function owns no memory, otherwise it will be leaked.
112+
impl<F: FnOnce()> OnDrop<F> {
113+
/// Disables on-drop call.
110114
#[inline]
111-
pub fn disable(self) {
112-
std::mem::forget(self);
115+
pub fn disable(mut self) {
116+
self.0.take();
113117
}
114118
}
115119

116-
impl<F: Fn()> Drop for OnDrop<F> {
120+
impl<F: FnOnce()> Drop for OnDrop<F> {
117121
#[inline]
118122
fn drop(&mut self) {
119-
(self.0)();
123+
if let Some(f) = self.0.take() {
124+
f();
125+
}
120126
}
121127
}
122128

compiler/rustc_data_structures/src/owned_slice/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use std::{
77
};
88

99
use crate::{
10+
defer,
1011
owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
11-
OnDrop,
1212
};
1313

1414
#[test]
@@ -66,7 +66,7 @@ fn boxed() {
6666
fn drop_drops() {
6767
let flag = Arc::new(AtomicBool::new(false));
6868
let flag_prime = Arc::clone(&flag);
69-
let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
69+
let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
7070

7171
let slice = slice_owned(d, |_| &[]);
7272

compiler/rustc_interface/src/interface.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use crate::util;
33
use rustc_ast::token;
44
use rustc_ast::{self as ast, LitKind, MetaItemKind};
55
use rustc_codegen_ssa::traits::CodegenBackend;
6+
use rustc_data_structures::defer;
67
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
78
use rustc_data_structures::sync::Lrc;
8-
use rustc_data_structures::OnDrop;
99
use rustc_errors::registry::Registry;
1010
use rustc_errors::{ErrorGuaranteed, Handler};
1111
use rustc_lint::LintStore;
@@ -325,7 +325,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
325325

326326
rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
327327
let r = {
328-
let _sess_abort_error = OnDrop(|| {
328+
let _sess_abort_error = defer(|| {
329329
compiler.sess.finish_diagnostics(registry);
330330
});
331331

compiler/rustc_middle/src/ty/context/tls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ where
7878
{
7979
TLV.with(|tlv| {
8080
let old = tlv.replace(erase(context));
81-
let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
81+
let _reset = rustc_data_structures::defer(move || tlv.set(old));
8282
f()
8383
})
8484
}

compiler/rustc_query_system/src/query/job.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use {
2222
rustc_data_structures::fx::FxHashSet,
2323
rustc_data_structures::sync::Lock,
2424
rustc_data_structures::sync::Lrc,
25-
rustc_data_structures::{jobserver, OnDrop},
25+
rustc_data_structures::{defer, jobserver},
2626
rustc_span::DUMMY_SP,
2727
std::iter,
2828
std::process,
@@ -530,7 +530,7 @@ fn remove_cycle<D: DepKind>(
530530
/// all active queries for cycles before finally resuming all the waiters at once.
531531
#[cfg(parallel_compiler)]
532532
pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
533-
let on_panic = OnDrop(|| {
533+
let on_panic = defer(|| {
534534
eprintln!("deadlock handler panicked, aborting process");
535535
process::abort();
536536
});

0 commit comments

Comments
 (0)