proc_macro_assertions/
add_generics.rs1use better_any::TidAble;
2
3use crate::{
4 assert::Assert, assertable::Assertable, generatable::Generatable, into_template::TypeEq,
5 maybe_borrowed::MaybeBorrowed, raw_assert::RawAssert,
6};
7
8pub struct WithGenerics<'a, T> {
11 pub data: T,
13 pub generics: Option<MaybeBorrowed<'a, syn::Generics>>,
15}
16
17pub trait AttachGenerics<'a> {
20 type Output;
24
25 fn with_generics<G>(self, generics: G) -> WithGenerics<'a, Self::Output>
31 where
32 G: Into<MaybeBorrowed<'a, syn::Generics>>,
33 Self: Sized,
34 {
35 self.with_optional_generics(Some(generics))
36 }
37
38 fn with_optional_generics<G>(self, generics: Option<G>) -> WithGenerics<'a, Self::Output>
39 where
40 G: Into<MaybeBorrowed<'a, syn::Generics>>;
41}
42
43pub trait AttachGenericsWithAssert<'a, A> {
46 type Output;
50
51 fn with_generics<B>(
57 self,
58 generics: impl Into<MaybeBorrowed<'a, syn::Generics>>,
59 ) -> WithGenerics<'a, Self::Output>
60 where
61 B: TypeEq<This = A>,
62 Self: Sized,
63 {
64 self.with_optional_generics::<B>(Some(generics))
65 }
66
67 fn with_optional_generics<B>(
68 self,
69 generics: Option<impl Into<MaybeBorrowed<'a, syn::Generics>>>,
70 ) -> WithGenerics<'a, Self::Output>
71 where
72 B: TypeEq<This = A>;
73}
74
75impl<'a, Gen, A> AttachGenericsWithAssert<'a, A> for Gen
76where
77 Gen: Generatable<'a, A>,
78 A: 'a + TidAble<'a>,
79{
80 type Output = MaybeBorrowed<'a, Self>;
81
82 fn with_optional_generics<B>(
83 self,
84 generics: Option<impl Into<MaybeBorrowed<'a, syn::Generics>>>,
85 ) -> WithGenerics<'a, Self::Output>
86 where
87 B: TypeEq<This = A>,
88 {
89 WithGenerics {
90 data: self.into(),
91 generics: generics.map(Into::into),
92 }
93 }
94}
95
96impl<'a, Gen> AttachGenerics<'a> for MaybeBorrowed<'a, Gen> {
97 type Output = MaybeBorrowed<'a, Gen>;
98
99 fn with_optional_generics<G>(self, generics: Option<G>) -> WithGenerics<'a, Self::Output>
100 where
101 G: Into<MaybeBorrowed<'a, syn::Generics>>,
102 {
103 WithGenerics {
104 data: self,
105 generics: generics.map(Into::into),
106 }
107 }
108}
109
110impl<'a, Gen, A> AttachGenerics<'a> for Assert<'a, Gen, A>
111where
112 Gen: Generatable<'a, A>,
113 A: 'a + TidAble<'a>,
114{
115 type Output = Assert<'a, Gen, A>;
116
117 fn with_optional_generics<G>(self, generics: Option<G>) -> WithGenerics<'a, Self::Output>
118 where
119 G: Into<MaybeBorrowed<'a, syn::Generics>>,
120 {
121 WithGenerics {
122 data: self,
123 generics: generics.map(Into::into),
124 }
125 }
126}
127
128impl<'a, G, A> Assertable<'a> for WithGenerics<'a, Assert<'a, G, A>>
129where
130 G: Generatable<'a, A> + Eq + Ord,
131 A: Eq + Ord + TidAble<'a>,
132{
133 type Output = RawAssert<'a, G, A>;
134
135 fn do_assert(self) -> RawAssert<'a, G, A> {
136 RawAssert {
137 template: self.data.template,
138 generics: check_generics(self.generics),
139 assert: self.data.assert,
140 }
141 }
142}
143
144fn check_generics(
145 generics: Option<MaybeBorrowed<syn::Generics>>,
146) -> Option<MaybeBorrowed<syn::Generics>> {
147 generics.and_then(|f| {
148 if f.lt_token.is_some()
149 && f.gt_token.is_some()
150 && !f.params.is_empty()
151 && f.where_clause
152 .as_ref()
153 .is_some_and(|w| !w.predicates.is_empty())
154 {
155 Some(f)
156 } else {
157 None
158 }
159 })
160}