Skip to content

Commit 6f674d3

Browse files
committed
1. Correction of comments in case of panic.
2. The lib.rs file has become lighter. 3. Correction of auto-generation of necessary traits for ManuallyDrop. 4. Adding missing shell elements for compatibility with older software. 5. Additional commenting of flags in Cargo.toml. 6. Flags have been added to control the controlled behavior of ManuallyDrop in the case of SafeManuallyDrop, now you can set a specific Hook / Panic / Counter / Loop behavior, if these flags are not set then the autodetector will be used as before. *_---
1 parent 232682a commit 6f674d3

File tree

11 files changed

+719
-429
lines changed

11 files changed

+719
-429
lines changed

Cargo.toml

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,78 @@
11
[package]
22
name = "SafeManuallyDrop"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
authors = ["Denis Kotlyarov <[email protected]>"]
55
edition = "2021"
66

77
[features]
88
default = [
9+
# The ManuallyDrop type is always SafeManuallyDrop if the debug_assertions flag
10+
# is active (test build, debug build).
911
"always_check_in_case_debug_assertions",
12+
13+
# The ManuallyDrop type is always SafeManuallyDrop,
14+
# i.e. with traceable behavior.
15+
#"always_safe_manuallydrop",
16+
17+
# For compatibility with older software, create a separate crate::core::hook
18+
# instead of the new crate::core::trig::hook.
1019
"enable_deprecated_hook",
1120

21+
# Support for PanicManuallyDrop, in case of undefined behavior
22+
# of PanicManuallyDrop there will be a panic.
1223
"support_panic_trig",
13-
"support_hook_trig" #,
14-
#"support_count_trig"
24+
25+
# HookManuallyDrop support, in case of undefined HookManuallyDrop behavior,
26+
# the hook function will be called.
27+
"support_hookfn_trig" #,
28+
29+
# Support for CounterManuallyDrop, in case of undefined behavior,
30+
# CounterManuallyDrop will add +1 to the counter.
31+
#"support_count_trig" #,
32+
33+
# The behavior for the simple ManuallyDrop type will always
34+
# cause a panic in case of undefined behavior.
35+
#"always_deftrig_panic",
36+
37+
# The behavior for the simple ManuallyDrop type will always
38+
# call the hook function in case of undefined behavior.
39+
#"always_deftrig_hookfn",
40+
41+
# The behavior for the simple ManuallyDrop type will always call
42+
# the +1 counter function in case of undefined behavior.
43+
#"always_deftrig_count",
44+
45+
# The behavior for the simple type ManuallyDrop will always call
46+
# the eternal loop function in case of undefined behavior.
47+
#"always_deftrig_loop"
48+
49+
# INFO:
50+
# If the behavior for the general MannuallyDrop is not fixed,
51+
# the behavior will be determined according to the following scheme:
52+
#
53+
# always_deftrig_panic not exists AND
54+
# always_deftrig_hookfn not exists AND
55+
# always_deftrig_count not exists AND
56+
# always_deftrig_loop not exists THEN
57+
#
58+
# support_hookfn_trig -> Hook, else:
59+
# support_panic_trig -> Panic, else:
60+
# support_count_trig -> Count, else:
61+
# Loop
62+
#
1563
]
1664
always_check_in_case_debug_assertions = []
1765
always_safe_manuallydrop = []
1866

19-
support_hook_trig = []
67+
support_hookfn_trig = []
2068
support_count_trig = []
2169
support_panic_trig = []
2270

2371
enable_deprecated_hook = []
2472

73+
always_deftrig_panic = []
74+
always_deftrig_hookfn = []
75+
always_deftrig_count = []
76+
always_deftrig_loop = []
77+
2578
[dependencies]

src/beh/safe.rs

Lines changed: 26 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,62 @@
11

2-
use core::hash::Hash;
32
use crate::UnsafeStdManuallyDrop;
43
use crate::core::trig::TrigManuallyDrop;
54
use core::marker::PhantomData;
65

76
/// A safe version of the insecure manual control of freeing memory.
87
// #[repr(transparent)]
9-
//#[derive(/*Copy,*/ Clone, Debug)]
10-
#[derive(/*Copy,*/ Clone, Debug/*, Default, PartialEq, Eq, PartialOrd, Ord, Hash*/)]
118
pub struct SafeManuallyDrop<T, Trig> where T: ?Sized, Trig: TrigManuallyDrop {
12-
pub (crate) state: StateManuallyDrop,
13-
pub (crate) _pp: PhantomData<Trig>,
14-
pub (crate) value: UnsafeStdManuallyDrop<T>,
9+
state: StateManuallyDrop,
10+
_pp: PhantomData<Trig>,
11+
value: UnsafeStdManuallyDrop<T>,
1512
}
1613

1714
crate::__codegen! {
1815
@use;
19-
#SafeManuallyDrop [is_safe: true];
16+
#SafeManuallyDrop [
17+
is_safe: true
18+
];
2019
}
2120

22-
//impl<T> Copy for ManuallyDrop<T> where T: ?Sized + Copy {} TODO
23-
24-
impl<T, Trig> Default for SafeManuallyDrop<T, Trig> where T: ?Sized + Default, Trig: TrigManuallyDrop {
21+
impl<T, Trig> SafeManuallyDrop<T, Trig> where T: ?Sized + Clone, Trig: TrigManuallyDrop {
22+
/// For tests only, resets the MannualuDrop state to the initial state
2523
#[inline(always)]
26-
fn default() -> Self {
27-
Self::new(
28-
Default::default()
29-
)
30-
}
31-
}
32-
33-
impl<T, Trig, Rhs> PartialEq<Rhs> for SafeManuallyDrop<T, Trig> where T: ?Sized + PartialEq<Rhs>, Trig: TrigManuallyDrop {
34-
#[inline]
35-
fn eq(&self, a: &Rhs) -> bool {
36-
let value: &T = self.value.deref();
37-
PartialEq::<Rhs>::eq(value, a)
38-
}
39-
40-
#[inline]
41-
fn ne(&self, a: &Rhs) -> bool {
42-
let value: &T = self.value.deref();
43-
PartialEq::<Rhs>::ne(value, a)
44-
}
45-
}
46-
47-
impl<T, Trig> Eq for SafeManuallyDrop<T, Trig> where T: Eq + PartialEq<SafeManuallyDrop<T, Trig>>, Trig: TrigManuallyDrop {
48-
#[inline]
49-
fn assert_receiver_is_total_eq(&self) {
50-
let value: &T = self.value.deref();
51-
Eq::assert_receiver_is_total_eq(value)
24+
pub unsafe fn flush(&mut self) -> StateManuallyDropData {
25+
self.state.flush()
5226
}
5327
}
5428

55-
impl<T, Trig> Ord for SafeManuallyDrop<T, Trig> where T: Ord + PartialOrd<SafeManuallyDrop<T, Trig>>, Trig: TrigManuallyDrop {
56-
#[inline]
57-
fn cmp(&self, a: &Self) -> core::cmp::Ordering {
58-
let value: &T = self.value.deref();
59-
Ord::cmp(value, a)
60-
}
61-
}
62-
63-
impl<T, Trig, Rhs> PartialOrd<Rhs> for SafeManuallyDrop<T, Trig> where T: ?Sized + PartialOrd<Rhs>, Trig: TrigManuallyDrop {
64-
#[inline]
65-
fn partial_cmp(&self, a: &Rhs) -> Option<core::cmp::Ordering> {
66-
let value: &T = self.value.deref();
67-
PartialOrd::partial_cmp(value, a)
68-
}
69-
}
29+
//impl<T> Copy for ManuallyDrop<T> where T: ?Sized + Copy {} TODO
7030

71-
impl<T, Trig> Hash for SafeManuallyDrop<T, Trig> where T: ?Sized + Hash, Trig: TrigManuallyDrop {
72-
#[inline]
73-
fn hash<H>(&self, a: &mut H) where H: core::hash::Hasher {
74-
let value: &T = self.value.deref();
75-
Hash::hash(value, a)
31+
impl<T, Trig> Clone for SafeManuallyDrop<T, Trig> where T: ?Sized + Clone, Trig: TrigManuallyDrop {
32+
#[inline(always)]
33+
fn clone(&self) -> Self {
34+
let state = self.state.clone();
35+
let ref_value: &T = self.value.deref();
36+
37+
Self {
38+
state,
39+
value: UnsafeStdManuallyDrop::new(Clone::clone(ref_value)),
40+
_pp: PhantomData,
41+
}
7642
}
7743
}
7844

7945
impl<T, Trig> Drop for SafeManuallyDrop<T, Trig> where T: ?Sized, Trig: TrigManuallyDrop {
8046
#[inline]
81-
fn drop(&mut self) {
82-
let ref mut value = self.value;
83-
let ref state = self.state;
84-
47+
fn drop(&mut self) {
8548
/*enum __HideTrig {}
8649
impl TrigManuallyDrop for __HideTrig {
8750
fn trig_next_invalid_beh<'a>(a: core::fmt::Arguments<'a>) -> ! {
8851
Trig::trig_next_invalid_beh(a)
8952
}
9053
}*/
9154

92-
state.if_empty_then_run_trigfn::<Trig, _>(
55+
self.state.if_empty_then_run_trigfn::<Trig, _>(
56+
"expected ManuallyDrop::drop(&mut value)",
9357
|| unsafe {
9458
// What for? - >> to ignore miri errors allocate.
95-
UnsafeStdManuallyDrop::drop(value);
59+
UnsafeStdManuallyDrop::drop(&mut self.value);
9660
}
9761
);
9862
}

src/beh/unsafe.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,33 @@ use crate::core::trig::TrigManuallyDrop;
55

66
/// Insecure standard implementation of manual memory management.
77
#[repr(transparent)]
8-
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
98
pub struct UnsafeManuallyDrop<T, Trig> where T: ?Sized, Trig: TrigManuallyDrop {
109
_pp: PhantomData<Trig>,
1110
value: UnsafeStdManuallyDrop<T>,
1211
}
1312

1413
crate::__codegen! {
1514
@use;
16-
#UnsafeManuallyDrop [is_safe: false];
15+
#UnsafeManuallyDrop [
16+
is_safe: false
17+
];
18+
}
19+
20+
impl<T, Trig> UnsafeManuallyDrop<T, Trig> where T: ?Sized + Clone, Trig: TrigManuallyDrop {
21+
/// For tests only, resets the MannualuDrop state to the initial state
22+
#[inline(always)]
23+
pub unsafe fn flush(&mut self) -> StateManuallyDropData {
24+
StateManuallyDropData::empty()
25+
}
26+
}
27+
28+
impl<T, Trig> Copy for UnsafeManuallyDrop<T, Trig> where T: ?Sized + Copy, Trig: TrigManuallyDrop {}
29+
30+
impl<T, Trig> Clone for UnsafeManuallyDrop<T, Trig> where T: ?Sized + Clone, Trig: TrigManuallyDrop {
31+
#[inline(always)]
32+
fn clone(&self) -> Self {
33+
Self::new(
34+
Clone::clone(&self.value)
35+
)
36+
}
1737
}

src/core/flags.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,25 +88,50 @@ crate::cfg_if_safemode! {
8888
#if_safe (pub const IS_SAFE_MODE: bool = true;)
8989
}
9090

91-
#[cfg(feature = "support_panic_trig")]
92-
pub const SUPPORT_PANIC_TRIG: bool = true;
93-
94-
#[cfg(not(feature = "support_panic_trig"))]
95-
pub const SUPPORT_PANIC_TRIG: bool = false;
96-
97-
#[cfg(feature = "support_hook_trig")]
98-
pub const SUPPORT_HOOK_TRIG: bool = true;
91+
#[deprecated(since = "0.1.5", note = "Use `IS_SUPPORT_PANIC_TRIG` instead")]
92+
pub const SUPPORT_PANIC_TRIG: bool = IS_SUPPORT_PANIC_TRIG;
93+
pub const IS_SUPPORT_PANIC_TRIG: bool = {
94+
#[cfg(feature = "support_panic_trig")] {
95+
true
96+
}
97+
98+
#[cfg(not(feature = "support_panic_trig"))] {
99+
false
100+
}
101+
};
99102

100-
#[cfg(not(feature = "support_hook_trig"))]
101-
pub const SUPPORT_HOOK_TRIG: bool = false;
103+
#[deprecated(since = "0.1.5", note = "Use `IS_SUPPORT_HOOKFN_TRIG` instead")]
104+
pub const SUPPORT_HOOKFN_TRIG: bool = IS_SUPPORT_HOOKFN_TRIG;
105+
pub const IS_SUPPORT_HOOKFN_TRIG: bool = {
106+
#[cfg(feature = "support_hookfn_trig")] {
107+
true
108+
}
109+
110+
#[cfg(not(feature = "support_hookfn_trig"))] {
111+
false
112+
}
113+
};
102114

103-
#[cfg(feature = "support_count_trig")]
104-
pub const SUPPORT_COUNT_TRIG: bool = true;
115+
#[deprecated(since = "0.1.5", note = "Use `IS_SUPPORT_COUNT_TRIG` instead")]
116+
pub const SUPPORT_COUNT_TRIG: bool = IS_SUPPORT_COUNT_TRIG;
117+
pub const IS_SUPPORT_COUNT_TRIG: bool = {
118+
#[cfg(feature = "support_count_trig")] {
119+
true
120+
}
121+
122+
#[cfg(not(feature = "support_count_trig"))] {
123+
false
124+
}
125+
};
105126

106-
#[cfg(not(feature = "support_count_trig"))]
107-
pub const SUPPORT_COUNT_TRIG: bool = false;
127+
#[deprecated(since = "0.1.5", note = "Use `IS_SUPPORT_EMPTY_TRIG` instead")]
128+
pub const SUPPORT_EMPTY_TRIG: bool = IS_SUPPORT_EMPTY_TRIG;
129+
pub const IS_SUPPORT_EMPTY_TRIG: bool = true;
108130

109-
pub const SUPPORT_EMPTY_TRIG: bool = true;
131+
pub const IS_AUTO_DETECT_DEFTRIG: bool = crate::core::trig::IS_AUTO_DETECT_DEFTRIG;
132+
/// If the build was done using "all functions" (cargo test/doc/build --all-features), the required behavior in a safe mandrop cannot be determined,
133+
/// if this flag is active, EmptyLoopTrigManuallyDrop will be used.
134+
pub const IS_INVALID_AUTO_DETECT_DEFTRIG: bool = crate::core::trig::IS_INVALID_AUTO_DETECT_DEFTRIG;
110135

111136
#[cfg(test)]
112137
#[test]

src/core/state.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
#[cfg(feature = "support_panic_trig")]
33
use crate::core::trig::panic::PanicTrigManuallyDrop;
4-
use crate::TrigManuallyDrop;
4+
use crate::core::trig::TrigManuallyDrop;
55
use core::fmt::Debug;
66
use core::sync::atomic::Ordering;
77
use core::sync::atomic::AtomicU8;
@@ -234,6 +234,16 @@ impl StateManuallyDrop {
234234
}
235235
}
236236

237+
/// For tests only, resets the MannualuDrop state to the initial state
238+
pub unsafe fn flush(&mut self) -> StateManuallyDropData {
239+
let result = self.__force_write(
240+
StateManuallyDropData::Empty
241+
);
242+
debug_assert_eq!(self.is_next_trig(), false);
243+
244+
result
245+
}
246+
237247
#[inline]
238248
fn __safe_replace_mutstate<Trig: TrigManuallyDrop>(&self, new_state: StateManuallyDropData) {
239249
debug_assert_eq!(new_state.is_next_trig(), true);
@@ -244,7 +254,7 @@ impl StateManuallyDrop {
244254
if old_state.is_next_trig() {
245255
Trig::trig_next_invalid_beh(
246256
format_args!(
247-
"SafeManuallyDrop, undef_beh (combo_replace_state), SafeManuallyDrop::empty() != {:?}",
257+
"Undefined behavior when using ManuallyDrop(combo_replace_manudropstate), instead of the expected default state, the current state: {:?}.",
248258
old_state
249259
)
250260
);
@@ -326,7 +336,7 @@ impl StateManuallyDrop {
326336

327337
Trig::trig_next_invalid_beh(
328338
format_args!(
329-
"SafeManuallyDrop, undef_beh (deref_or_panic), SafeManuallyDrop::no_panic_state() != {:?}",
339+
"Undefined behavior when using ManuallyDrop.deref(), instead of the expected default state, the current state: {:?}.",
330340
a_state
331341
)
332342
)
@@ -339,7 +349,7 @@ impl StateManuallyDrop {
339349
if a_state.is_next_trig() {
340350
Trig::trig_next_invalid_beh(
341351
format_args!(
342-
"SafeManuallyDrop, undef_beh (deref_or_trig), SafeManuallyDrop::no_panic_state() != {:?}",
352+
"Undefined behavior when using ManuallyDrop.deref(), instead of the expected default state, the current state: {:?}.",
343353
a_state
344354
)
345355
)
@@ -364,15 +374,16 @@ impl StateManuallyDrop {
364374
}
365375
}
366376

367-
pub fn if_empty_then_run_trigfn<Trig: TrigManuallyDrop, F: FnOnce()>(&self, fn_trig: F) {
377+
pub fn if_empty_then_run_trigfn<Trig: TrigManuallyDrop, F: FnOnce()>(&self, exp_str: &'static str, fn_trig: F) {
368378
let a_state = self.read();
369379

370380
if a_state.is_empty() {
371381
fn_trig();
372382

373383
Trig::trig_next_invalid_beh(
374384
format_args!(
375-
"SafeManuallyDrop, undef_beh (exp_def_state), SafeManuallyDrop::empty() == {:?}",
385+
"Undefined behavior when using ManuallyDrop ({}), state should not be default, current state is {:?}.",
386+
exp_str,
376387
a_state
377388
)
378389
)

0 commit comments

Comments
 (0)