//! ## ZST Callbacks //! //! ``` //! use valrow::*; //! //! #[derive(Debug)] pub struct ZST(()); // N.B.: not copyable for whatever reason! //! unsafe impl valrow::Borrowable for ZST { type Abi = (); } // ✔️ sound //! //! let zst = ZST(()); //! let zst_ref = &zst; //! let zst_borrow = Valrow::new(&zst); //! //! # #[cfg(wont_compile)] // rejected by StaticAssert::::IS_ZST //! call_callback(move || { dbg!(zst_ref); }); // ❌ won't compile: `zst_ref` isn't a ZST //! call_callback(move || { dbg!(zst_borrow); }); // ✔️ will compile: `zst_borrow` *is* a ZST //! //! fn call_callback(mut callback: Callback) { //! let callback = &mut callback; //! unsafe { call_callback(adapt::) }; //! let _ = callback; //! //! # #[cfg(nope)] { //! #[link(name = "clibrary")] extern "C" { fn call_callback(callback: extern "C" fn()); } //! # } //! # unsafe fn call_callback(callback: extern "C" fn()) { callback() } //! extern "C" fn adapt() { //! // ⚠️ assume only `call_callback` calls `adapt` (has a `&mut Callback` on the stack) //! let _ = StaticAssert::::IS_ZST; // otherwise we need a real address //! let callback = unsafe { core::ptr::NonNull::::dangling().as_mut() }; //! callback(); //! } //! } //! struct StaticAssert(T); //! impl StaticAssert { const IS_ZST : () = assert!(0 == core::mem::size_of::()); } //! ```