Skip to main content

tenferro_tensor/
native_session.rs

1//! Lifetime-bound native session capability tokens.
2//!
3//! A backend leaf crate (CPU, CUDA, WebGPU) exposes its concrete execution
4//! session to higher-level operation crates through a [`NativeSessionRef`]
5//! returned by [`BackendSession::native_session`](crate::BackendSession::native_session).
6//! The token is opaque: its fields are private and its only constructor is
7//! `unsafe`, so safe code can neither fabricate one nor retarget it at another
8//! value. A backend leaf recovers its own session with a safe visitor that
9//! checks the token's marker against a marker type only that leaf can name.
10//!
11//! This narrows the unsafe boundary to each leaf's constructor and visitor; it
12//! does not remove it.
13//!
14//! # Examples
15//!
16//! A session without native services returns no token, which is the default:
17//!
18//! ```rust
19//! use tenferro_tensor::{BackendSession, NativeSessionRef};
20//!
21//! fn has_native_services(session: &mut dyn BackendSession) -> bool {
22//!     session.native_session().is_some()
23//! }
24//! ```
25//!
26//! The token borrows its session exclusively and cannot outlive that borrow:
27//!
28//! ```compile_fail
29//! use tenferro_tensor::{BackendSession, NativeSessionRef};
30//!
31//! fn escape(session: &mut dyn BackendSession) -> NativeSessionRef<'static> {
32//!     session.native_session().unwrap()
33//! }
34//! ```
35//!
36//! It cannot be built from safe code, even with a private marker type:
37//!
38//! ```compile_fail,E0133
39//! use tenferro_tensor::NativeSessionRef;
40//!
41//! struct Marker;
42//! let mut value = 0_u8;
43//! let _token = NativeSessionRef::new::<Marker, u8>(&mut value);
44//! ```
45//!
46//! It is neither `Send` nor `Clone`, so it cannot leave its thread or be
47//! duplicated into a second exclusive borrow:
48//!
49//! ```compile_fail,E0277
50//! fn require_send<T: Send>(_: T) {}
51//! fn check(token: tenferro_tensor::NativeSessionRef<'_>) {
52//!     require_send(token);
53//! }
54//! ```
55//!
56//! ```compile_fail,E0599
57//! fn duplicate(token: tenferro_tensor::NativeSessionRef<'_>) {
58//!     let _second = token.clone();
59//!     let _first = token;
60//! }
61//! ```
62
63use std::any::TypeId;
64use std::fmt;
65use std::marker::PhantomData;
66use std::ptr::NonNull;
67
68/// An exclusively borrowed backend-leaf execution session.
69///
70/// The token names one concrete session by a backend-leaf marker type and
71/// borrows it for `'s`. It is not `Clone`, `Copy`, `Send` or `Sync`. Only the
72/// backend leaf that owns the marker can recover the session, through its own
73/// safe visitor; custom sessions either return no token or forward the token of
74/// a standard delegate they own.
75///
76/// # Examples
77///
78/// ```rust
79/// use tenferro_tensor::{BackendSession, NativeSessionRef};
80///
81/// struct Marker;
82///
83/// fn is_marked(token: &NativeSessionRef<'_>) -> bool {
84///     token.has_marker::<Marker>()
85/// }
86///
87/// fn inspect(session: &mut dyn BackendSession) -> bool {
88///     session.native_session().is_some_and(|token| is_marked(&token))
89/// }
90/// ```
91pub struct NativeSessionRef<'s> {
92    marker: TypeId,
93    session: NonNull<()>,
94    _borrow: PhantomData<&'s mut ()>,
95    _not_send_sync: PhantomData<*mut ()>,
96}
97
98impl<'s> NativeSessionRef<'s> {
99    /// Create a token that names `session` by the backend-leaf marker `M`.
100    ///
101    /// # Safety
102    ///
103    /// `M` must be a marker type private to the calling backend leaf crate,
104    /// and every token that crate creates with `M` must point to a value of the
105    /// single concrete session type its visitor recovers for `M`. `session`
106    /// is exclusively borrowed for `'s`, which the signature enforces; the
107    /// visitor relies on the marker/type correspondence for its cast.
108    ///
109    /// # Examples
110    ///
111    /// ```rust
112    /// use tenferro_tensor::NativeSessionRef;
113    ///
114    /// struct LeafSession(u32);
115    /// struct LeafMarker;
116    ///
117    /// let mut session = LeafSession(7);
118    /// // SAFETY: `LeafMarker` is private to this example and names `LeafSession`.
119    /// let token = unsafe { NativeSessionRef::new::<LeafMarker, _>(&mut session) };
120    /// let pointer = token.into_marked_ptr::<LeafMarker>().expect("same marker");
121    /// // SAFETY: the marker proved the pointee is `LeafSession`, and the
122    /// // exclusive borrow of `session` is still held here.
123    /// assert_eq!(unsafe { pointer.cast::<LeafSession>().as_ref().0 }, 7);
124    /// ```
125    pub unsafe fn new<M: 'static, S>(session: &'s mut S) -> Self {
126        Self {
127            marker: TypeId::of::<M>(),
128            session: NonNull::from(session).cast(),
129            _borrow: PhantomData,
130            _not_send_sync: PhantomData,
131        }
132    }
133
134    /// Whether this token was created with the backend-leaf marker `M`.
135    ///
136    /// # Examples
137    ///
138    /// ```rust
139    /// use tenferro_tensor::NativeSessionRef;
140    ///
141    /// struct Marker;
142    /// struct Other;
143    /// let mut value = 0_u8;
144    /// // SAFETY: `Marker` is private to this example and names `u8`.
145    /// let token = unsafe { NativeSessionRef::new::<Marker, _>(&mut value) };
146    /// assert!(token.has_marker::<Marker>());
147    /// assert!(!token.has_marker::<Other>());
148    /// ```
149    #[must_use]
150    pub fn has_marker<M: 'static>(&self) -> bool {
151        self.marker == TypeId::of::<M>()
152    }
153
154    /// Consume the token and return its session pointer when it carries `M`.
155    ///
156    /// Returning the pointer is safe; dereferencing it is the backend leaf's
157    /// audited step. The leaf may only do so while the borrow the token was
158    /// created from is still held, which its visitor guarantees by holding the
159    /// `&mut` session for the whole visit.
160    ///
161    /// # Examples
162    ///
163    /// ```rust
164    /// use tenferro_tensor::NativeSessionRef;
165    ///
166    /// struct Marker;
167    /// struct Other;
168    /// let mut value = 3_u8;
169    /// // SAFETY: `Marker` is private to this example and names `u8`.
170    /// let token = unsafe { NativeSessionRef::new::<Marker, _>(&mut value) };
171    /// assert!(token.into_marked_ptr::<Other>().is_none());
172    /// ```
173    #[must_use]
174    pub fn into_marked_ptr<M: 'static>(self) -> Option<NonNull<()>> {
175        self.has_marker::<M>().then_some(self.session)
176    }
177}
178
179impl fmt::Debug for NativeSessionRef<'_> {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        f.debug_struct("NativeSessionRef").finish_non_exhaustive()
182    }
183}