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.
This commit is contained in:
Matthias Krüger 2023-05-25 08:01:08 +02:00 committed by GitHub
commit a9743e108a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 15 deletions

View file

@ -102,21 +102,27 @@ pub mod unord;
pub use ena::undo_log; pub use ena::undo_log;
pub use ena::unify; pub use ena::unify;
pub struct OnDrop<F: Fn()>(pub F); /// Returns a structure that calls `f` when dropped.
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
OnDrop(Some(f))
}
impl<F: Fn()> OnDrop<F> { pub struct OnDrop<F: FnOnce()>(Option<F>);
/// Forgets the function which prevents it from running.
/// Ensure that the function owns no memory, otherwise it will be leaked. impl<F: FnOnce()> OnDrop<F> {
/// Disables on-drop call.
#[inline] #[inline]
pub fn disable(self) { pub fn disable(mut self) {
std::mem::forget(self); self.0.take();
} }
} }
impl<F: Fn()> Drop for OnDrop<F> { impl<F: FnOnce()> Drop for OnDrop<F> {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
(self.0)(); if let Some(f) = self.0.take() {
f();
}
} }
} }

View file

@ -7,8 +7,8 @@ use std::{
}; };
use crate::{ use crate::{
defer,
owned_slice::{slice_owned, try_slice_owned, OwnedSlice}, owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
OnDrop,
}; };
#[test] #[test]
@ -66,7 +66,7 @@ fn boxed() {
fn drop_drops() { fn drop_drops() {
let flag = Arc::new(AtomicBool::new(false)); let flag = Arc::new(AtomicBool::new(false));
let flag_prime = Arc::clone(&flag); let flag_prime = Arc::clone(&flag);
let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed)); let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
let slice = slice_owned(d, |_| &[]); let slice = slice_owned(d, |_| &[]);

View file

@ -3,9 +3,9 @@ use crate::util;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::{self as ast, LitKind, MetaItemKind}; use rustc_ast::{self as ast, LitKind, MetaItemKind};
use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::defer;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::OnDrop;
use rustc_errors::registry::Registry; use rustc_errors::registry::Registry;
use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_lint::LintStore; use rustc_lint::LintStore;
@ -325,7 +325,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
let r = { let r = {
let _sess_abort_error = OnDrop(|| { let _sess_abort_error = defer(|| {
compiler.sess.finish_diagnostics(registry); compiler.sess.finish_diagnostics(registry);
}); });

View file

@ -78,7 +78,7 @@ where
{ {
TLV.with(|tlv| { TLV.with(|tlv| {
let old = tlv.replace(erase(context)); let old = tlv.replace(erase(context));
let _reset = rustc_data_structures::OnDrop(move || tlv.set(old)); let _reset = rustc_data_structures::defer(move || tlv.set(old));
f() f()
}) })
} }

View file

@ -22,7 +22,7 @@ use {
rustc_data_structures::fx::FxHashSet, rustc_data_structures::fx::FxHashSet,
rustc_data_structures::sync::Lock, rustc_data_structures::sync::Lock,
rustc_data_structures::sync::Lrc, rustc_data_structures::sync::Lrc,
rustc_data_structures::{jobserver, OnDrop}, rustc_data_structures::{defer, jobserver},
rustc_span::DUMMY_SP, rustc_span::DUMMY_SP,
std::iter, std::iter,
std::process, std::process,
@ -530,7 +530,7 @@ fn remove_cycle<D: DepKind>(
/// all active queries for cycles before finally resuming all the waiters at once. /// all active queries for cycles before finally resuming all the waiters at once.
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) { pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
let on_panic = OnDrop(|| { let on_panic = defer(|| {
eprintln!("deadlock handler panicked, aborting process"); eprintln!("deadlock handler panicked, aborting process");
process::abort(); process::abort();
}); });