From a573ce99a3386eb53b7d5d050710fac8287a45ed Mon Sep 17 00:00:00 2001 From: willtunnels Date: Sat, 7 Aug 2021 20:22:18 -0400 Subject: [PATCH 1/3] Use ManuallyDrop instead of mem::forget in into_inner --- src/lib.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d33c2b6..8a3e845 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -193,7 +193,7 @@ extern crate core as std; use std::fmt; use std::marker::PhantomData; -use std::mem::{self, ManuallyDrop}; +use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; use std::ptr; @@ -346,16 +346,15 @@ impl ScopeGuard /// ``` #[inline] pub fn into_inner(guard: Self) -> T { - // Cannot move out of Drop-implementing types, so - // ptr::read the value and forget the guard. + // Cannot move out of Drop-implementing types, so ptr::read the value + // and forget the guard. + let guard = ManuallyDrop::new(guard); unsafe { let value = ptr::read(&*guard.value); - // read the closure so that it is dropped, and assign it to a local - // variable to ensure that it is only dropped after the guard has - // been forgotten. (In case the Drop impl of the closure, or that - // of any consumed captured variable, panics). - let _dropfn = ptr::read(&*guard.dropfn); - mem::forget(guard); + // Read the closure so that it gets dropped. Do this after value has + // also been read so that, if the closure's drop function panics, + // unwinding still tries to drop value. + ptr::read(&*guard.dropfn) value } } From e9add36894d74beae6640dc87c6e966454c39550 Mon Sep 17 00:00:00 2001 From: willtunnels Date: Sun, 8 Aug 2021 05:58:43 -0400 Subject: [PATCH 2/3] Improve comments in ScopeGuard::into_inner --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8a3e845..fe287ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -346,15 +346,15 @@ impl ScopeGuard /// ``` #[inline] pub fn into_inner(guard: Self) -> T { - // Cannot move out of Drop-implementing types, so ptr::read the value - // and forget the guard. + // Cannot move out of `Drop`-implementing types, + // so `ptr::read` the value and forget the guard. let guard = ManuallyDrop::new(guard); unsafe { let value = ptr::read(&*guard.value); - // Read the closure so that it gets dropped. Do this after value has - // also been read so that, if the closure's drop function panics, - // unwinding still tries to drop value. - ptr::read(&*guard.dropfn) + // Read the closure, so that it gets dropped. Do this after `value` has + // been read, so that if the closure's `drop` function panics, + // unwinding still tries to drop `value`. + ptr::read(&*guard.dropfn); value } } From c7fe76f03df1be8b8a00b72def728fa61f22cd81 Mon Sep 17 00:00:00 2001 From: willtunnels Date: Sun, 8 Aug 2021 22:59:11 -0400 Subject: [PATCH 3/3] Drop dropfn in place --- src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fe287ac..78afc9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,13 +348,13 @@ impl ScopeGuard pub fn into_inner(guard: Self) -> T { // Cannot move out of `Drop`-implementing types, // so `ptr::read` the value and forget the guard. - let guard = ManuallyDrop::new(guard); + let mut guard = ManuallyDrop::new(guard); unsafe { let value = ptr::read(&*guard.value); - // Read the closure, so that it gets dropped. Do this after `value` has - // been read, so that if the closure's `drop` function panics, - // unwinding still tries to drop `value`. - ptr::read(&*guard.dropfn); + // Drop the closure after `value` has been read, so that if the + // closure's `drop` function panics, unwinding still tries to drop + // `value`. + ManuallyDrop::drop(&mut guard.dropfn); value } }