1#![allow(non_snake_case, unused_imports)]
2
3extern crate proc_macro;
4
5#[macro_use]
6extern crate fstrings;
7
8use ::proc_macro::{
9 TokenStream,
10};
11use ::proc_macro2::{
12 Span,
13 TokenStream as TokenStream2,
14};
15use ::quote::{
16 quote,
17 quote_spanned,
18};
19use ::syn::{*,
20 parse::{
21 Parse,
22 ParseStream,
23 },
24 spanned::Spanned,
25};
26use ::std::{*,
27 convert::{TryInto, TryFrom},
28 iter::FromIterator,
29 result::Result,
30};
31
32#[macro_use]
33mod macros;
34
35#[inline]
36fn take<T : Default> (x: &'_ mut T)
37 -> T
38{
39 mem::replace(x, T::default())
40}
41
42#[proc_macro_attribute] pub
43fn inheritable (params: TokenStream, input: TokenStream)
44 -> TokenStream
45{
46 #[cfg_attr(feature = "verbose-expansions",
48 derive(Debug),
49 )]
50 #[allow(dead_code)] struct Trait {
52 ident: Ident,
53 methods: Vec<TraitItemMethod>,
54 }
55
56 impl Parse for Trait {
57 fn parse (input: ParseStream) -> syn::Result<Self>
58 {Ok({
59 let ItemTrait {
60 ident,
61 items,
62 generics,
63 ..
64 } = input.parse()?
65 ;
66 match (
67 generics.type_params().next(),
68 generics.lifetimes().next(),
69 generics.const_params().next(),
70 )
71 {
72 | (None, None, None) => {},
73
74 | _ => parse_error!(
75 generics.span(),
76 "Trait generics are not supported (yet)",
77 ),
78 }
79 let methods: Vec<TraitItemMethod> =
80 items
81 .into_iter()
82 .map(|trait_item| match trait_item {
84 | TraitItem::Method(method) => Ok(method),
85 | _ => parse_error!(
86 trait_item.span(),
87 "`#[inheritable]` currently only supports methods"
88 ),
89 })
90 .map(|x| x.and_then(|method| {
92 let ref sig = method.sig;
93 let mut span = sig.ident.span();
94 match sig.inputs.iter().next() {
95 | Some(&FnArg::Receiver(Receiver {
97 reference: Some(_),
98 ..
99 }))
100 => {},
101
102 | Some(&FnArg::Typed(PatType {
104 ref pat,
105 ref ty,
106 ..
107 }))
108 if match (&**pat, &**ty) {
109 | (
110 &Pat::Ident(PatIdent { ref ident, .. }),
111 &Type::Reference(_),
112 ) => {
113 ident == "self"
114 },
115
116 | _ => false,
117 }
118 => {},
119
120 | opt_arg => {
122 if let Some(arg) = opt_arg {
123 span = arg.span();
124 }
125 parse_error!(span, concat!(
126 "associated function requires a ",
127 "`&self` or `&mut self` receiver",
128 ));
129 },
130 }
131 Ok(method)
132 }))
133 .collect::<Result<_, _>>()?
134 ;
135 Self {
136 ident,
137 methods,
138 }
139 })}
140 }
141
142
143 set_output!( render => ret );
144
145 debug!(concat!(
146 "-------------------------\n",
147 "#[inheritable({params})]\n",
148 "{input}\n",
149 ), params=params, input=input);
150
151
152 let params = TokenStream2::from(params);
154 if params.clone().into_iter().next().is_some() {
155 error!(params.span(), "Unexpected parameter(s)");
156 }
157
158 let Trait {
160 ident: Trait,
161 mut methods,
162 } = {
163 let input = input.clone();
164 parse_macro_input!(input)
165 };
166
167
168 ret.extend(input);
170
171
172 let InheritsTrait = Ident::new(&f!(
174 "__Inherits{Trait}__"
175 ), Span::call_site());
176
177 ret.extend({
178 use ::proc_macro::*;
182 iter::once(TokenTree::Punct(Punct::new(
183 '#',
184 Spacing::Alone))).chain(TokenStream::from(::quote::quote! {
185 [doc(hidden)]
186 }))
187 });
188 render! {
189 pub(in crate)
190 trait #InheritsTrait {
191 type __Parent__
192 : #Trait
193 ;
194 fn __parent__ (self: &'_ Self)
195 -> &'_ Self::__Parent__
196 ;
197 fn __parent_mut__ (self: &'_ mut Self)
198 -> &'_ mut Self::__Parent__
199 ;
200 }
201 };
202
203
204 methods
206 .iter_mut()
207 .for_each(|method| {
208 let &mut TraitItemMethod {
209 sig: Signature {
210 ref ident,
211 ref generics,
212 ref mut inputs,
213 ..
214 },
215 ref mut default,
216 ref mut semi_token,
217 ref mut attrs,
218 } = method;
219 *attrs = vec![];
220 *semi_token = None;
221 let mut args: Vec<Ident> =
222 Vec::with_capacity(
223 inputs
224 .len()
225 .saturating_sub(1)
226 )
227 ;
228 let mut inputs_iter = take(inputs).into_iter();
229 let mut parent_mb_mut = TokenStream2::default();
230 *inputs =
231 inputs_iter
232 .next()
233 .map(|first_arg| {
234 if match first_arg {
235 | FnArg::Receiver(Receiver {
236 ref mutability,
237 ..
238 }) => {
239 mutability.is_some()
240 },
241 | FnArg::Typed(PatType { ref ty, .. }) => {
243 match &**ty {
244 | &Type::Reference(TypeReference {
245 ref mutability,
246 ..
247 }) => {
248 mutability.is_some()
249 },
250
251 | _ => unreachable!(),
252 }
253 },
254 } {
255 parent_mb_mut = quote!( __parent_mut__ );
256 } else {
257 parent_mb_mut = quote!( __parent__ );
258 }
259 first_arg
260 })
261 .into_iter()
262 .chain(
263 inputs_iter
264 .zip(1 ..)
265 .map(|(mut arg, i)| match arg {
266 | FnArg::Typed(PatType { ref mut pat, .. }) => {
267 let ident = Ident::new(&f!(
268 "arg_{i}"
269 ), Span::call_site());
270 *pat = parse_quote! {
271 #ident
272 };
273 args.push(ident);
274 arg
275 },
276
277 | _ => unreachable!("Invalid method signature"),
278 })
279 )
280 .collect()
281 ;
282 let generics = generics.split_for_impl().1;
283 let generics = generics.as_turbofish();
284 *default = Some(parse_quote! {
286 {
287 self.#parent_mb_mut()
297 .#ident #generics (
298 #(#args),*
299 )
300 }
301 });
302 })
303 ;
304 let default_if_specialization =
305 if cfg!(feature = "specialization") {
306 quote!( default )
307 } else {
308 TokenStream2::new()
309 }
310 ;
311 render! {
312 impl<__inheritable_T__ : #InheritsTrait> #Trait
313 for __inheritable_T__
314 {
315 #(
316 #[inline]
317 #default_if_specialization
318 #methods
319 )*
320 }
321 }
322
323
324 debug!("=> becomes =>\n\n{}\n-------------------------\n", ret);
325
326
327 ret
328}
329
330#[proc_macro_derive(Inheritance, attributes(inherits))] pub
331fn derive_Inheritance (input: TokenStream)
332 -> TokenStream
333{
334 debug!(concat!(
335 "-------------------------\n",
336 "#[derive(Inheritance)]\n",
337 "{input}\n",
338 "\n",
339 ), input=input);
340
341 set_output!( render => ret );
342
343 let DeriveInput {
344 ident: Struct,
345 generics,
346 data,
347 ..
348 } = parse_macro_input!(input)
349 ;
350 let fields = match data {
351 | Data::Struct(DataStruct { fields, .. }) => fields,
352 | Data::Enum(r#enum) => {
353 error!(r#enum.enum_token.span(),
354 "enums are not supported"
355 );
356 },
357 | Data::Union(r#union) => {
358 error!(r#union.union_token.span(),
359 "unions are not supported"
360 );
361 },
362 };
363 let (mut iter1, mut iter2);
364 let fields: &mut dyn Iterator<Item = Field> = match fields {
365 | Fields::Unit => {
366 iter1 = iter::empty();
367 &mut iter1
368 },
369 | Fields::Unnamed(fields) => {
370 iter2 = fields.unnamed.into_iter();
371 &mut iter2
372 },
373 | Fields::Named(fields) => {
374 iter2 = fields.named.into_iter();
375 &mut iter2
376 },
377 };
378 let ref inherits: Ident = parse_quote! {
379 inherits
380 };
381 for (i, mut field) in fields.enumerate() {
382 let (path_to_InheritsTrait, span) =
383 match take(&mut field.attrs)
384 .into_iter()
385 .find_map(|attr| if attr.path.is_ident(inherits) { Some({
386 let span = attr.span();
387 attr.parse_args_with(Path::parse_mod_style)
388 .map(|mut path| {
389 let last =
390 path.segments
391 .iter_mut()
392 .last()
393 .expect("path has at least one segment")
394 ;
395 let ref Trait = last.ident;
396 let InheritsTrait = Ident::new(&f!(
397 "__Inherits{Trait}__"
398 ), span);
399 *last = parse_quote! {
400 #InheritsTrait
401 };
402 (path, span)
403 })
404 })} else {
405 None
406 })
407 {
408 | None => continue,
409 | Some(Err(err)) => return err.to_compile_error().into(),
410 | Some(Ok(inner)) => inner,
411 }
412 ;
413 let field_name =
414 if let Some(ref ident) = field.ident {
415 quote! {
416 #ident
417 }
418 } else {
419 let i: Index = i.into();
420 quote! {
421 #i
422 }
423 }
424 ;
425 let ref FieldType = field.ty;
426 let (impl_generics, ty_generics, where_clause) =
427 generics.split_for_impl()
428 ;
429 render! { span =>
430 impl #impl_generics #path_to_InheritsTrait
431 for #Struct #ty_generics
432 #where_clause
433 {
434 type __Parent__ = #FieldType;
435
436 #[inline]
437 fn __parent__ (self: &'_ Self)
438 -> &'_ Self::__Parent__
439 {
440 &self.#field_name
441 }
442
443 #[inline]
444 fn __parent_mut__ (self: &'_ mut Self)
445 -> &'_ mut Self::__Parent__
446 {
447 &mut self.#field_name
448 }
449 }
450 }
451 }
452 debug!("=> generates =>\n\n{}\n-------------------------\n", ret);
453 ret
454}