use crate::private;
pub trait IrqlLevel: private::Sealed {}
#[diagnostic::on_unimplemented(
message = "IRQL violation: cannot reach `{Target}` from `{Self}` -- would require lowering",
label = "cannot lower IRQL",
note = "IRQL can only stay the same or be raised, never lowered"
)]
pub trait IrqlCanRaiseTo<Target: IrqlLevel>: private::Sealed {}
#[diagnostic::on_unimplemented(
message = "IRQL violation: `{Self}` is below the required minimum `{Target}`",
label = "IRQL too low",
note = "this operation requires IRQL >= `{Target}`"
)]
pub trait IrqlCanLowerTo<Target: IrqlLevel>: private::Sealed {}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be safely dropped at IRQL `{Level}`",
label = "not safe to drop at this IRQL",
note = "this type (or a type it contains) has opted out via a negative impl.\nConsider passing by reference (`&`) or transferring ownership without dropping (e.g. `leak()` / `into_raw()`)."
)]
pub trait SafeToDropAt<Level: IrqlLevel> {}
macro_rules! define_irql_hierarchy {
($($level:ident),+) => {
$(
#[doc = concat!(
"IRQL level: **", stringify!($level), "**.\n",
"\n",
"See [`IrqlLevel`] for the full hierarchy.",
)]
pub struct $level;
impl private::Sealed for $level {}
impl IrqlLevel for $level {}
)+
define_irql_hierarchy!(@raise_all $($level),+);
define_irql_hierarchy!(@lower_all $($level),+);
};
(@raise_all $head:ident, $($tail:ident),+) => {
impl IrqlCanRaiseTo<$head> for $head {}
$( impl IrqlCanRaiseTo<$tail> for $head {} )+
define_irql_hierarchy!(@raise_all $($tail),+);
};
(@raise_all $last:ident) => {
impl IrqlCanRaiseTo<$last> for $last {}
};
(@lower_all $head:ident, $($tail:ident),+) => {
impl IrqlCanLowerTo<$head> for $head {}
$( impl IrqlCanLowerTo<$head> for $tail {} )+
define_irql_hierarchy!(@lower_all $($tail),+);
};
(@lower_all $last:ident) => {
impl IrqlCanLowerTo<$last> for $last {}
};
}
define_irql_hierarchy!(
Passive, Apc, Dispatch, Dirql, Profile, Clock, Ipi, Power, High
);
#[cfg(not(feature = "drop-safety"))]
impl<T, L: IrqlLevel> SafeToDropAt<L> for T {}