use core::{convert::Infallible, ops::Add};
#[sealed::sealed]
pub trait DropKind {
type NeedsDrop: DropKind;
}
pub(crate) type NeedsDrop<T> = <T as DropKind>::NeedsDrop;
pub enum NoDrop {}
pub enum AutoDrop {}
pub struct CustomDrop<I: DropKind>(core::marker::PhantomData<I>, Infallible);
#[sealed::sealed]
impl DropKind for NoDrop {
type NeedsDrop = NoDrop;
}
#[sealed::sealed]
impl DropKind for AutoDrop {
type NeedsDrop = AutoDrop;
}
#[sealed::sealed]
impl<K: DropKind> DropKind for CustomDrop<K> {
type NeedsDrop = AutoDrop;
}
impl<I: DropKind> Add<I> for NoDrop {
type Output = I::NeedsDrop;
fn add(self, _: I) -> Self::Output {
unreachable!()
}
}
impl<Rhs> Add<Rhs> for AutoDrop {
type Output = Self;
fn add(self, _: Rhs) -> Self::Output {
unreachable!()
}
}
impl Add<NoDrop> for CustomDrop<NoDrop> {
type Output = AutoDrop;
fn add(self, _: NoDrop) -> Self::Output {
unreachable!()
}
}
impl Add<AutoDrop> for CustomDrop<NoDrop> {
type Output = AutoDrop;
fn add(self, _: AutoDrop) -> Self::Output {
unreachable!()
}
}
impl<I: DropKind> Add<CustomDrop<I>> for CustomDrop<NoDrop> {
type Output = AutoDrop;
fn add(self, _: CustomDrop<I>) -> Self::Output {
unreachable!()
}
}
impl<Rhs> Add<Rhs> for CustomDrop<AutoDrop> {
type Output = AutoDrop;
fn add(self, _: Rhs) -> Self::Output {
unreachable!()
}
}