1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
mod r#trait;
mod r#type;
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use better_any::{Tid, TidAble};
use quote::ToTokens;
pub use r#trait::Trait;
pub use r#type::Type;
use proc_macro2::TokenStream;
use crate::maybe_borrowed::MaybeBorrowed;
use super::{context::Context, passed_data::PassedData};
/// This indicates that some type can be turned into tokens that assert something.
/// Be aware that this only relies on rust's type checking, the code that is generated
/// is never actually meant to be executed. The generation functions in three distinct "Stages".
/// See below for more information on that.
///
///
/// The type implementing this must also be [`TidAble`], which is similar to [`Any`](std::any::Any)
/// but allows for non-'static lifetimes. The easiest way to implement it is to use the derive macro (`#[derive(Tid)]`)
///
/// # Idents
/// There is a need to ensure that there are no ident collisions among the generated code.
/// For that purpose in each stage there is a context provided, which contains some [`IdentGenerator`](crate::ident_generator::IdentGenerator).
/// Other than Idents passed into the methods by either `Self` or any parameters, use Idents generates by the `IdentGenerator`
/// exclusively to avoid any collisions.
///
/// # Generation "Stages"
/// ## Stage 1: Generatable
/// These tokens are generated for each type that implemets this trait once. This is the perfect place to put
/// tokens that are needed as "Setup" for any asserts.
/// ## Stage 2: Template
/// These tokens are generated for each unique instance of `Self`. You should put any tokens that should be unique
/// for each instance in here.
/// ## Stage 3: Assert
/// These tokens are generated for each unique Assert, which represent some type that is tested against `Self`.
/// No generation is actually happening until at least one assert is created for `Self`.
///
/// # Passed Data
/// There may be a need to pass data, for example generated idents, between stages. For that purpose
/// this trait provides a way to do so. See [`PassedData`](crate::passed_data::PassedData) for more information.
pub trait Generatable<'a, Assert>
where
Self: TidAble<'a>,
Assert: 'a + TidAble<'a>,
{
/// The type of any data passed from the `Generatable` stage to proceeding stages.
type GeneratableData: 'a;
/// The type of any data passed from the `Template` stage to proceeding stages.
type TemplateData: 'a;
/// This is the method the `Generatable` stage is composed of. Should return Tokens (if any) generated by this stage,
/// plus optionally any data passed to preceding stages.
fn generatable(context: &mut Context) -> PassedData<Self::GeneratableData>
where
Self: Sized;
/// This is the method the `Template` stage is composed of. Should return Tokens (if any) generated by this stage,
/// plus optionally any data passed to preceding stages.
fn template(
&self,
context: &mut Context,
passed: &Self::GeneratableData,
) -> PassedData<Self::TemplateData>;
/// This is the method the `Assert` stage is composed of. Should return Tokens generated by this stage.
fn assert(
&self,
_context: &mut Context,
_passed: (&Self::GeneratableData, &Self::TemplateData),
_to_assert: &Assert,
) -> Option<TokenStream>;
}
#[derive(Tid)]
#[repr(transparent)]
pub struct StaticTid<T: 'static>(pub T);
impl<T: 'static> From<T> for StaticTid<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<'a, T> From<&'a T> for &'a StaticTid<T> {
fn from(value: &'a T) -> Self {
// Safe because StaticTid is #[repr(transparent)].
unsafe { &*(value as *const T).cast::<StaticTid<T>>() }
}
}
impl<'a, T> From<&'a mut T> for &'a mut StaticTid<T> {
fn from(value: &'a mut T) -> Self {
// Safe because StaticTid is #[repr(transparent)].
unsafe { &mut *(value as *mut T).cast::<StaticTid<T>>() }
}
}
impl<'a, U> From<&'a U> for MaybeBorrowed<'a, StaticTid<U>> {
fn from(value: &'a U) -> Self {
MaybeBorrowed::Borrowed(value.into())
}
}
impl<'a, T> From<T> for MaybeBorrowed<'a, StaticTid<T>> {
fn from(value: T) -> Self {
MaybeBorrowed::Owned(StaticTid(value))
}
}
impl<T: 'static> Deref for StaticTid<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: 'static> DerefMut for StaticTid<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: 'static + ToTokens> ToTokens for StaticTid<T> {
fn to_tokens(&self, tokens: &mut TokenStream) {
(**self).to_tokens(tokens);
}
}
impl<T: 'static + PartialEq> PartialEq for StaticTid<T> {
fn eq(&self, other: &Self) -> bool {
(**self).eq(&**other)
}
}
impl<T: 'static + Eq> Eq for StaticTid<T> {}
impl<T: 'static + PartialOrd> PartialOrd for StaticTid<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<T: 'static + Ord> Ord for StaticTid<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(**self).cmp(&**other)
}
}
impl<T: 'static + Hash> Hash for StaticTid<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}