mod private {
pub trait Sealed {}
}
use crate::TryDropStrategy;
use core::marker::PhantomData;
pub trait Safety: private::Sealed {}
#[cfg_attr(
feature = "derives",
derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
)]
pub enum Safe {}
impl Safety for Safe {}
impl private::Sealed for Safe {}
#[cfg(feature = "ds-unreachable-unsafe")]
#[cfg_attr(
feature = "derives",
derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
)]
pub enum Unsafe {}
#[cfg(feature = "ds-unreachable-unsafe")]
impl Safety for Unsafe {}
#[cfg(feature = "ds-unreachable-unsafe")]
impl private::Sealed for Unsafe {}
#[cfg_attr(
feature = "derives",
derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
)]
pub struct UnreachableDropStrategy<S: Safety>(PhantomData<S>);
impl UnreachableDropStrategy<Safe> {
pub const SAFE: Self = Self::safe();
pub const fn safe() -> Self {
UnreachableDropStrategy(PhantomData)
}
}
#[cfg(feature = "ds-unreachable-unsafe")]
impl UnreachableDropStrategy<Unsafe> {
pub const UNSAFE: Self = Self::r#unsafe();
pub const fn r#unsafe() -> Self {
UnreachableDropStrategy(PhantomData)
}
}
impl Default for UnreachableDropStrategy<Safe> {
fn default() -> Self {
Self::safe()
}
}
impl TryDropStrategy for UnreachableDropStrategy<Safe> {
fn handle_error(&self, error: crate::Error) {
unreachable!("this error should not happen: {}", error)
}
}
#[cfg(feature = "ds-unreachable-unsafe")]
impl TryDropStrategy for UnreachableDropStrategy<Unsafe> {
fn handle_error(&self, error: crate::Error) {
#[cfg(debug_assertions)]
unreachable!(
"panicking due to `debug_assertions` (debug profile), this error should not happen: {}",
error
);
#[cfg(not(debug_assertions))]
unsafe {
core::hint::unreachable_unchecked()
}
}
}
#[cfg(test)]
mod tests {
use crate::test_utils::fallible;
use super::*;
#[test]
#[should_panic(expected = "internal error: entered unreachable code: this error should not happen: this will always fail")]
fn test_unreachable_drop_strategy_safe() {
let unreachable = UnreachableDropStrategy::safe();
crate::install_thread_local_handlers(unreachable, unreachable);
drop(fallible());
}
#[test]
#[should_panic(expected = "internal error: entered unreachable code: panicking due to `debug_assertions` (debug profile), this error should not happen: this will always fail")]
#[cfg(debug_assertions)]
fn test_unreachable_drop_strategy_unsafe_debug_assertions() {
let unreachable = UnreachableDropStrategy::r#unsafe();
crate::install_thread_local_handlers(unreachable, unreachable);
drop(fallible());
}
}