tola_caps/spec/compile.rs
1//! # Compile-Time Trait Detection
2//!
3//! This module provides low-level trait detection utilities.
4//!
5//! ## User API
6//!
7//! For most use cases, prefer the `caps_check!` macro which supports
8//! boolean expressions like `Clone & !Copy`:
9//!
10//! ```ignore
11//! use tola_caps::caps_check;
12//!
13//! assert!(caps_check!(String: Clone));
14//! assert!(caps_check!(String: Clone & !Copy));
15//! ```
16//!
17//! ## Low-level: `has_impl!`
18//!
19//! For detecting arbitrary traits on concrete types:
20//!
21//! ```
22//! use tola_caps::has_impl;
23//!
24//! trait MyTrait {}
25//! impl MyTrait for i32 {}
26//!
27//! assert!(has_impl!(i32, MyTrait));
28//! assert!(!has_impl!(String, MyTrait));
29//! ```
30
31// =============================================================================
32// has_impl! - Low-level trait detection (concrete types only)
33// =============================================================================
34
35/// Check if a concrete type implements a trait at compile time.
36///
37/// Uses the "Inherent Const Fallback" pattern: an inherent const shadows
38/// a trait const when the bound is satisfied.
39///
40/// **Note**: Only works for concrete types. For generic contexts, use
41/// `caps_check!` with standard traits (Clone, Copy, Debug, Default, Send, Sync).
42///
43/// # Usage
44///
45/// ```
46/// use tola_caps::has_impl;
47///
48/// assert!(has_impl!(String, Clone));
49/// assert!(!has_impl!(String, Copy));
50///
51/// trait MyTrait {}
52/// impl MyTrait for i32 {}
53/// assert!(has_impl!(i32, MyTrait));
54/// ```
55#[macro_export]
56macro_rules! has_impl {
57 ($T:ty, $Trait:path) => {{
58 struct __Probe<T>(core::marker::PhantomData<T>);
59
60 trait __Fallback { const VAL: bool = false; }
61 impl<T> __Fallback for __Probe<T> {}
62
63 impl<T: $Trait> __Probe<T> {
64 #[allow(dead_code)]
65 const VAL: bool = true;
66 }
67
68 __Probe::<$T>::VAL
69 }};
70}
71
72// =============================================================================
73// define_trait_cap! - Register a user trait into the caps system
74// =============================================================================
75
76/// Define a capability marker for a user trait.
77///
78/// This macro generates a capability marker struct `Is<Trait>` with
79/// `#[derive(Capability)]` for integration with the type-level capability system.
80///
81/// # Usage
82///
83/// ```ignore
84/// trait Serialize { fn serialize(&self) -> Vec<u8>; }
85///
86/// define_trait_cap!(Serialize);
87///
88/// // Now IsSerialize can be used in capability sets
89/// ```
90#[macro_export]
91macro_rules! define_trait_cap {
92 ($Trait:ident) => {
93 $crate::paste::paste! {
94 /// Capability marker for detecting `$Trait` implementation.
95 #[derive($crate::Capability)]
96 pub struct [<Is $Trait>];
97 }
98 };
99}
100
101// =============================================================================
102// Tests
103// =============================================================================
104
105#[cfg(test)]
106mod tests {
107 #[test]
108 fn test_has_impl_std_traits() {
109 assert!(has_impl!(String, Clone));
110 assert!(has_impl!(i32, Clone));
111 assert!(has_impl!(i32, Copy));
112 assert!(!has_impl!(String, Copy));
113 assert!(has_impl!(i32, core::fmt::Debug));
114 }
115
116 #[test]
117 fn test_has_impl_custom_trait() {
118 #[allow(dead_code)]
119 trait MyTrait {}
120 impl MyTrait for i32 {}
121
122 assert!(has_impl!(i32, MyTrait));
123 assert!(!has_impl!(String, MyTrait));
124 }
125}
126