1use proc_macro2::TokenStream;
8
9use syn::{
10 bracketed,
11 fold::{self, Fold},
12 parenthesized,
13 parse::{Parse, ParseStream},
14 parse_quote,
15 spanned::Spanned,
16 token, Block, Error, Expr, ExprField, FnArg, Ident, ImplItem, ImplItemMethod, Index, ItemImpl,
17 Macro, Member, Result, Stmt, Type, WhereClause, WherePredicate,
18};
19
20use quote::{quote, ToTokens};
21
22const TUPLE_TYPES_NO_DEFAULT_TRAIT_BOUND: &str = "tuple_types_no_default_trait_bound";
25const TUPLE_TYPES_CUSTOM_TRAIT_BOUND: &str = "tuple_types_custom_trait_bound";
26
27enum Separator {
29 Comma(token::Comma),
30 Add(token::Add),
31 Sub(token::Sub),
32 Or(token::Or),
33 And(token::And),
34 Star(token::Star),
35 Div(token::Div),
36}
37
38impl Separator {
39 fn parse_before_star(input: ParseStream) -> Result<Option<Self>> {
41 if input.peek2(token::Star) {
42 Self::parse(input).map(Some)
43 } else {
44 Ok(None)
45 }
46 }
47
48 fn to_token_stream(&self, last: bool) -> TokenStream {
52 let empty_on_last = |token: &dyn ToTokens| {
53 if last {
54 TokenStream::default()
55 } else {
56 token.to_token_stream()
57 }
58 };
59
60 match self {
61 Self::Comma(comma) => comma.to_token_stream(),
62 Self::Add(add) => empty_on_last(add),
63 Self::Sub(sub) => empty_on_last(sub),
64 Self::Or(or) => empty_on_last(or),
65 Self::And(and) => empty_on_last(and),
66 Self::Star(star) => empty_on_last(star),
67 Self::Div(div) => empty_on_last(div),
68 }
69 }
70}
71
72impl Parse for Separator {
73 fn parse(input: ParseStream) -> Result<Self> {
74 let lookahead1 = input.lookahead1();
75
76 if lookahead1.peek(token::Comma) {
77 Ok(Self::Comma(input.parse()?))
78 } else if lookahead1.peek(token::Add) {
79 Ok(Self::Add(input.parse()?))
80 } else if lookahead1.peek(token::Sub) {
81 Ok(Self::Sub(input.parse()?))
82 } else if lookahead1.peek(token::Or) {
83 Ok(Self::Or(input.parse()?))
84 } else if lookahead1.peek(token::And) {
85 Ok(Self::And(input.parse()?))
86 } else if lookahead1.peek(token::Star) {
87 Ok(Self::Star(input.parse()?))
88 } else if lookahead1.peek(token::Div) {
89 Ok(Self::Div(input.parse()?))
90 } else {
91 Err(lookahead1.error())
92 }
93 }
94}
95
96enum Repetition {
98 Stmts(Vec<Stmt>),
99 Type(Type),
100 Where(WherePredicate),
101}
102
103struct TupleRepetition {
105 pub pound_token: token::Pound,
106 pub _paren_token: token::Paren,
107 pub repetition: Repetition,
108 pub separator: Option<Separator>,
109 pub _star_token: token::Star,
110}
111
112impl TupleRepetition {
113 fn parse_as_stmts(input: ParseStream) -> Result<Self> {
115 let content;
116 Ok(Self {
117 pound_token: input.parse()?,
118 _paren_token: parenthesized!(content in input),
119 repetition: Repetition::Stmts(content.call(Block::parse_within)?),
120 separator: Separator::parse_before_star(input)?,
121 _star_token: input.parse()?,
122 })
123 }
124
125 fn parse_as_where_predicate(input: ParseStream) -> Result<Self> {
127 let content;
128 Ok(Self {
129 pound_token: input.parse()?,
130 _paren_token: parenthesized!(content in input),
131 repetition: Repetition::Where(content.parse()?),
132 separator: Separator::parse_before_star(input)?,
133 _star_token: input.parse()?,
134 })
135 }
136
137 fn parse_as_type(input: ParseStream) -> Result<Self> {
139 let content;
140 Ok(Self {
141 pound_token: input.parse()?,
142 _paren_token: parenthesized!(content in input),
143 repetition: Repetition::Type(content.parse()?),
144 separator: Separator::parse_before_star(input)?,
145 _star_token: input.parse()?,
146 })
147 }
148
149 fn expand_as_stmts(
151 self,
152 tuple_placeholder_ident: &Ident,
153 tuples: &[Ident],
154 use_self: bool,
155 ) -> Result<TokenStream> {
156 let mut generated = TokenStream::new();
157 let span = self.pound_token.span();
158 let stmts = match self.repetition {
159 Repetition::Stmts(stmts) => stmts,
160 _ => return Err(Error::new(
161 span,
162 "Internal error, expected `repetition` to be of type `Stmts`! Please report this issue!",
163 )),
164 };
165
166 for (i, tuple) in tuples.iter().enumerate() {
167 generated.extend(stmts.iter().cloned().map(|s| {
168 ReplaceTuplePlaceholder::replace_ident_in_stmt(
169 tuple_placeholder_ident,
170 tuple,
171 use_self,
172 i,
173 s,
174 )
175 .map(|s| s.to_token_stream())
176 .unwrap_or_else(|e| e.to_compile_error())
177 }));
178
179 if let Some(ref sep) = self.separator {
180 generated.extend(sep.to_token_stream(i + 1 == tuples.len()));
181 }
182 }
183
184 Ok(generated)
185 }
186
187 fn expand_as_type_declaration(
189 self,
190 tuple_placeholder_ident: &Ident,
191 tuples: &[Ident],
192 ) -> Result<TokenStream> {
193 let mut generated = TokenStream::new();
194 let span = self.pound_token.span();
195 let ty = match self.repetition {
196 Repetition::Type(ty) => ty,
197 _ => return Err(Error::new(
198 span,
199 "Internal error, expected `repetition` to be of type `Type`! Please report this issue!",
200 )),
201 };
202
203 for (i, tuple) in tuples.iter().enumerate() {
204 generated.extend(
205 ReplaceTuplePlaceholder::replace_ident_in_type(tuple_placeholder_ident, tuple, ty.clone())
206 .map(|s| s.to_token_stream())
207 .unwrap_or_else(|e| e.to_compile_error()),
208 );
209
210 if let Some(ref sep) = self.separator {
211 generated.extend(sep.to_token_stream(i + 1 == tuples.len()));
212 }
213 }
214
215 Ok(generated)
216 }
217
218 fn expand_to_where_clause(
221 self,
222 tuple_placeholder_ident: &Ident,
223 tuples: &[Ident],
224 where_clause: &mut WhereClause,
225 ) -> Result<()> {
226 let span = self.pound_token.span();
227 let predicate = match self.repetition {
228 Repetition::Where(pred) => pred,
229 _ => return Err(Error::new(
230 span,
231 "Internal error, expected `repetition` to be of type `Where`! Please report this issue!",
232 )),
233 };
234
235 for tuple in tuples.iter() {
236 where_clause.predicates.push(
237 ReplaceTuplePlaceholder::replace_ident_in_where_predicate(
238 tuple_placeholder_ident,
239 tuple,
240 predicate.clone(),
241 )?,
242 );
243 }
244
245 Ok(())
246 }
247}
248
249struct ReplaceTuplePlaceholder<'a> {
251 search: &'a Ident,
252 replace: &'a Ident,
253 use_self: bool,
254 index: Index,
255 errors: Vec<Error>,
256}
257
258impl<'a> ReplaceTuplePlaceholder<'a> {
259 fn replace_ident_in_stmt(
261 search: &'a Ident,
262 replace: &'a Ident,
263 use_self: bool,
264 index: usize,
265 stmt: Stmt,
266 ) -> Result<Stmt> {
267 let mut folder = Self {
268 search,
269 replace,
270 use_self,
271 index: index.into(),
272 errors: Vec::new(),
273 };
274
275 let res = fold::fold_stmt(&mut folder, stmt);
276
277 if let Some(first) = folder.errors.pop() {
278 Err(folder.errors.into_iter().fold(first, |mut e, n| {
279 e.combine(n);
280 e
281 }))
282 } else {
283 Ok(res)
284 }
285 }
286
287 fn replace_ident_in_type(search: &'a Ident, replace: &'a Ident, type_: Type) -> Result<Type> {
289 let mut folder = Self {
290 search,
291 replace,
292 use_self: false,
293 index: 0.into(),
294 errors: Vec::new(),
295 };
296
297 let res = fold::fold_type(&mut folder, type_);
298
299 if let Some(first) = folder.errors.pop() {
300 Err(folder.errors.into_iter().fold(first, |mut e, n| {
301 e.combine(n);
302 e
303 }))
304 } else {
305 Ok(res)
306 }
307 }
308
309 fn replace_ident_in_where_predicate(
311 search: &'a Ident,
312 replace: &'a Ident,
313 where_predicate: WherePredicate,
314 ) -> Result<WherePredicate> {
315 let mut folder = Self {
316 search,
317 replace,
318 use_self: false,
319 index: 0.into(),
320 errors: Vec::new(),
321 };
322
323 let res = fold::fold_where_predicate(&mut folder, where_predicate);
324
325 if let Some(first) = folder.errors.pop() {
326 Err(folder.errors.into_iter().fold(first, |mut e, n| {
327 e.combine(n);
328 e
329 }))
330 } else {
331 Ok(res)
332 }
333 }
334}
335
336impl<'a> Fold for ReplaceTuplePlaceholder<'a> {
337 fn fold_ident(&mut self, ident: Ident) -> Ident {
338 if &ident == self.search {
339 self.replace.clone()
340 } else {
341 ident
342 }
343 }
344
345 fn fold_expr(&mut self, expr: Expr) -> Expr {
346 match expr {
347 Expr::MethodCall(mut call) => match *call.receiver {
348 Expr::Path(ref path) if path.path.is_ident(self.search) => {
349 if self.use_self {
350 let index = &self.index;
351 call.receiver = parse_quote!( self.#index );
352
353 call.into()
354 } else {
355 self.errors.push(Error::new(
356 path.span(),
357 "Can not call non-static method from within a static method.",
358 ));
359 Expr::Verbatim(Default::default())
360 }
361 }
362 _ => fold::fold_expr_method_call(self, call).into(),
363 },
364 _ => fold::fold_expr(self, expr),
365 }
366 }
367
368 fn fold_expr_field(&mut self, mut expr: ExprField) -> ExprField {
369 match expr.member {
370 Member::Named(ref ident) if ident == self.search => {
371 expr.member = Member::Unnamed(self.index.clone());
373 expr
374 }
375 _ => expr,
376 }
377 }
378}
379
380enum ConstExpr {
382 Simple { tuple_repetition: TupleRepetition },
384 RefArray {
386 and_token: token::And,
387 bracket_token: token::Bracket,
388 tuple_repetition: TupleRepetition,
389 },
390}
391
392impl ConstExpr {
393 fn expand(
395 self,
396 tuple_placeholder_ident: &Ident,
397 tuples: &[Ident],
398 use_self: bool,
399 ) -> Result<TokenStream> {
400 match self {
401 Self::Simple { tuple_repetition } => {
402 tuple_repetition.expand_as_stmts(tuple_placeholder_ident, tuples, use_self)
403 }
404 Self::RefArray {
405 and_token,
406 bracket_token,
407 tuple_repetition,
408 } => {
409 let repetition =
410 tuple_repetition.expand_as_stmts(tuple_placeholder_ident, tuples, use_self)?;
411
412 let mut token_stream = and_token.to_token_stream();
413 bracket_token.surround(&mut token_stream, |tokens| tokens.extend(repetition));
414 Ok(token_stream)
415 }
416 }
417 }
418}
419
420impl Parse for ConstExpr {
421 fn parse(input: ParseStream) -> Result<Self> {
422 let lookahead1 = input.lookahead1();
423
424 if lookahead1.peek(token::And) {
425 let content;
426 Ok(ConstExpr::RefArray {
427 and_token: input.parse()?,
428 bracket_token: bracketed!(content in input),
429 tuple_repetition: content.call(TupleRepetition::parse_as_stmts)?,
430 })
431 } else if lookahead1.peek(token::Pound) {
432 Ok(ConstExpr::Simple {
433 tuple_repetition: TupleRepetition::parse_as_stmts(input)?,
434 })
435 } else {
436 Err(lookahead1.error())
437 }
438 }
439}
440
441enum ForTuplesMacro {
443 ItemType {
445 type_token: token::Type,
446 ident: Ident,
447 equal_token: token::Eq,
448 paren_token: token::Paren,
449 tuple_repetition: TupleRepetition,
450 semi_token: token::Semi,
451 },
452 ItemConst {
454 const_token: token::Const,
455 ident: Ident,
456 colon_token: token::Colon,
457 const_type: Type,
458 equal_token: token::Eq,
459 expr: ConstExpr,
460 semi_token: token::Semi,
461 },
462 StmtParenthesized {
464 paren_token: token::Paren,
465 tuple_repetition: TupleRepetition,
466 },
467 Stmt { tuple_repetition: TupleRepetition },
469 Where {
471 _where_token: token::Where,
472 tuple_repetition: TupleRepetition,
473 },
474}
475
476impl Parse for ForTuplesMacro {
477 fn parse(input: ParseStream) -> Result<Self> {
478 let lookahead1 = input.lookahead1();
479
480 if lookahead1.peek(token::Type) {
481 let content;
482 Ok(ForTuplesMacro::ItemType {
483 type_token: input.parse()?,
484 ident: input.parse()?,
485 equal_token: input.parse()?,
486 paren_token: parenthesized!(content in input),
487 tuple_repetition: content.call(TupleRepetition::parse_as_type)?,
488 semi_token: input.parse()?,
489 })
490 } else if lookahead1.peek(token::Const) {
491 Ok(ForTuplesMacro::ItemConst {
492 const_token: input.parse()?,
493 ident: input.parse()?,
494 colon_token: input.parse()?,
495 const_type: input.parse()?,
496 equal_token: input.parse()?,
497 expr: input.parse()?,
498 semi_token: input.parse()?,
499 })
500 } else if lookahead1.peek(token::Paren) {
501 let content;
502 Ok(ForTuplesMacro::StmtParenthesized {
503 paren_token: parenthesized!(content in input),
504 tuple_repetition: content.call(TupleRepetition::parse_as_stmts)?,
505 })
506 } else if lookahead1.peek(token::Pound) {
507 Ok(ForTuplesMacro::Stmt {
508 tuple_repetition: input.call(TupleRepetition::parse_as_stmts)?,
509 })
510 } else if lookahead1.peek(token::Where) {
511 Ok(ForTuplesMacro::Where {
512 _where_token: input.parse()?,
513 tuple_repetition: input.call(TupleRepetition::parse_as_where_predicate)?,
514 })
515 } else {
516 Err(lookahead1.error())
517 }
518 }
519}
520
521impl ForTuplesMacro {
522 fn try_from(macro_item: &Macro, allow_where: bool) -> Result<Option<Self>> {
528 if !macro_item.path.is_ident("for_tuples") {
530 return Ok(None);
531 }
532
533 let res = macro_item.parse_body::<Self>()?;
534
535 if !allow_where && res.is_where() {
536 Err(Error::new(
537 macro_item.span(),
538 "Custom where clause not allowed at this position!",
539 ))
540 } else {
541 Ok(Some(res))
542 }
543 }
544
545 fn is_where(&self) -> bool {
547 matches!(self, Self::Where { .. })
548 }
549
550 fn into_where(self) -> Option<TupleRepetition> {
552 match self {
553 Self::Where {
554 tuple_repetition, ..
555 } => Some(tuple_repetition),
556 _ => None,
557 }
558 }
559
560 fn expand(
568 self,
569 tuple_placeholder_ident: &Ident,
570 tuples: &[Ident],
571 use_self: bool,
572 ) -> TokenStream {
573 match self {
574 Self::ItemType {
575 type_token,
576 ident,
577 equal_token,
578 paren_token,
579 tuple_repetition,
580 semi_token,
581 } => {
582 let mut token_stream = type_token.to_token_stream();
583 let repetition =
584 tuple_repetition.expand_as_type_declaration(tuple_placeholder_ident, tuples);
585
586 match repetition {
587 Ok(rep) => {
588 ident.to_tokens(&mut token_stream);
589 equal_token.to_tokens(&mut token_stream);
590 paren_token.surround(&mut token_stream, |tokens| tokens.extend(rep));
591 semi_token.to_tokens(&mut token_stream);
592 }
593 Err(e) => token_stream.extend(e.to_compile_error()),
594 }
595
596 token_stream
597 }
598 Self::ItemConst {
599 const_token,
600 ident,
601 colon_token,
602 const_type,
603 equal_token,
604 expr,
605 semi_token,
606 } => {
607 let mut token_stream = const_token.to_token_stream();
608
609 let expr = expr.expand(tuple_placeholder_ident, tuples, use_self);
610
611 match expr {
612 Ok(expr) => {
613 ident.to_tokens(&mut token_stream);
614 colon_token.to_tokens(&mut token_stream);
615 const_type.to_tokens(&mut token_stream);
616 equal_token.to_tokens(&mut token_stream);
617 token_stream.extend(expr);
618 semi_token.to_tokens(&mut token_stream);
619 }
620 Err(e) => token_stream.extend(e.to_compile_error()),
621 }
622
623 token_stream
624 }
625 Self::StmtParenthesized {
626 paren_token,
627 tuple_repetition,
628 } => {
629 let mut token_stream = TokenStream::new();
630 let repetition =
631 tuple_repetition.expand_as_stmts(tuple_placeholder_ident, tuples, use_self);
632
633 match repetition {
634 Ok(rep) => {
635 paren_token.surround(&mut token_stream, |tokens| tokens.extend(rep))
636 }
637 Err(e) => token_stream.extend(e.to_compile_error()),
638 }
639
640 token_stream
641 }
642 Self::Stmt { tuple_repetition } => tuple_repetition
643 .expand_as_stmts(tuple_placeholder_ident, tuples, use_self)
644 .unwrap_or_else(|e| e.to_compile_error()),
645 Self::Where { .. } => TokenStream::new(),
646 }
647 }
648}
649
650fn add_tuple_elements_generics(
652 tuples: &[Ident],
653 mut trait_impl: ItemImpl,
654 bound: Option<TokenStream>,
655) -> Result<ItemImpl> {
656 crate::utils::add_tuple_element_generics(tuples, bound, &mut trait_impl.generics);
657 Ok(trait_impl)
658}
659
660struct ToTupleImplementation<'a> {
662 tuples: &'a [Ident],
664 tuple_placeholder_ident: &'a Ident,
668 errors: Vec<Error>,
670 has_self_parameter: bool,
672 custom_where_clause: Option<TupleRepetition>,
674}
675
676#[derive(Debug)]
678struct BoundsStruct {
679 _paren_token: token::Paren,
680 bounds: syn::TypeTraitObject,
681}
682
683impl Parse for BoundsStruct {
684 fn parse(input: ParseStream) -> Result<Self> {
685 let content;
686 Ok(BoundsStruct {
687 _paren_token: parenthesized!(content in input),
688 bounds: content.parse()?,
689 })
690 }
691}
692
693impl<'a> ToTupleImplementation<'a> {
694 fn generate_implementation(
696 trait_impl: &ItemImpl,
697 tuple_placeholder_ident: &'a Ident,
698 tuples: &'a [Ident],
699 ref_tuples: bool,
700 ) -> Result<TokenStream> {
701 let mut to_tuple = ToTupleImplementation {
702 tuples,
703 errors: Vec::new(),
704 tuple_placeholder_ident,
705 has_self_parameter: false,
706 custom_where_clause: None,
707 };
708
709 let mut res = fold::fold_item_impl(&mut to_tuple, trait_impl.clone());
710
711 let default_trait = trait_impl.trait_.clone().map(|t| t.1).ok_or_else(|| {
712 Error::new(
713 trait_impl.span(),
714 "The semi-automatic implementation is required to implement a trait!",
715 )
716 })?;
717
718 let trait_ = if let Some(pos) = res
720 .attrs
721 .iter()
722 .position(|a| a.path.is_ident(TUPLE_TYPES_CUSTOM_TRAIT_BOUND))
723 {
724 let attr = &res.attrs[pos];
726 let input = attr.tokens.to_token_stream();
727 let result = syn::parse2::<BoundsStruct>(input);
728 let trait_name = match result {
729 Ok(b) => b.bounds,
730 Err(e) => {
731 return Err(Error::new(
732 e.span(),
733 format!("Invalid trait bound: {}", e.to_string()),
734 ))
735 }
736 };
737
738 res.attrs.remove(pos);
739 quote! { #trait_name }
740 } else {
741 quote! { #default_trait }
742 };
743
744 let add_bound = if let Some(pos) = res
746 .attrs
747 .iter()
748 .position(|a| a.path.is_ident(TUPLE_TYPES_NO_DEFAULT_TRAIT_BOUND))
749 {
750 res.attrs.remove(pos);
751 None
752 } else {
753 Some(trait_)
754 };
755
756 let mut res = add_tuple_elements_generics(tuples, res, add_bound)?;
758 if ref_tuples {
760 res.self_ty = parse_quote!( ( #( &#tuples, )* ) );
761 } else {
762 res.self_ty = parse_quote!( ( #( #tuples, )* ) );
763 };
764 res.attrs.push(parse_quote!(#[allow(unused)]));
765
766 if let Some(where_clause) = to_tuple.custom_where_clause.take() {
767 where_clause.expand_to_where_clause(
768 tuple_placeholder_ident,
769 tuples,
770 res.generics.make_where_clause(),
771 )?;
772 }
773
774 if let Some(first_error) = to_tuple.errors.pop() {
775 Err(to_tuple.errors.into_iter().fold(first_error, |mut e, n| {
776 e.combine(n);
777 e
778 }))
779 } else {
780 Ok(res.to_token_stream())
781 }
782 }
783
784 fn custom_fold_expr(&mut self, expr: Expr) -> (Expr, bool) {
786 match expr {
787 Expr::Macro(expr_macro) => match ForTuplesMacro::try_from(&expr_macro.mac, false) {
788 Ok(Some(for_tuples)) => (
789 Expr::Verbatim(for_tuples.expand(
790 &self.tuple_placeholder_ident,
791 self.tuples,
792 self.has_self_parameter,
793 )),
794 true,
795 ),
796 Ok(None) => (fold::fold_expr_macro(self, expr_macro).into(), false),
797 Err(e) => {
798 self.errors.push(e);
799 (Expr::Verbatim(Default::default()), false)
800 }
801 },
802 _ => (fold::fold_expr(self, expr), false),
803 }
804 }
805}
806
807impl<'a> Fold for ToTupleImplementation<'a> {
808 fn fold_impl_item(&mut self, i: ImplItem) -> ImplItem {
809 match i {
810 ImplItem::Macro(macro_item) => match ForTuplesMacro::try_from(¯o_item.mac, true) {
811 Ok(Some(for_tuples)) => {
812 if for_tuples.is_where() {
813 if self.custom_where_clause.is_some() {
814 self.errors.push(Error::new(
815 macro_item.span(),
816 "Only one custom where clause is supported!",
817 ));
818 } else {
819 self.custom_where_clause = for_tuples.into_where();
820 }
821
822 ImplItem::Verbatim(Default::default())
823 } else {
824 ImplItem::Verbatim(for_tuples.expand(
825 &self.tuple_placeholder_ident,
826 self.tuples,
827 false,
828 ))
829 }
830 }
831 Ok(None) => fold::fold_impl_item_macro(self, macro_item).into(),
832 Err(e) => {
833 self.errors.push(e);
834 ImplItem::Verbatim(Default::default())
835 }
836 },
837 _ => fold::fold_impl_item(self, i),
838 }
839 }
840
841 fn fold_expr(&mut self, expr: Expr) -> Expr {
842 self.custom_fold_expr(expr).0
843 }
844
845 fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
846 let (expr, trailing_semi) = match stmt {
847 Stmt::Expr(expr) => (expr, None),
848 Stmt::Semi(expr, semi) => (expr, Some(semi)),
849 _ => return fold::fold_stmt(self, stmt),
850 };
851
852 let (expr, expanded) = self.custom_fold_expr(expr);
853
854 if expanded {
855 Stmt::Expr(expr)
856 } else if let Some(semi) = trailing_semi {
857 Stmt::Semi(expr, semi)
858 } else {
859 Stmt::Expr(expr)
860 }
861 }
862
863 fn fold_type(&mut self, ty: Type) -> Type {
864 match ty {
865 Type::Macro(ty_macro) => match ForTuplesMacro::try_from(&ty_macro.mac, false) {
866 Ok(Some(for_tuples)) => Type::Verbatim(for_tuples.expand(
867 &self.tuple_placeholder_ident,
868 self.tuples,
869 false,
870 )),
871 Ok(None) => fold::fold_type_macro(self, ty_macro).into(),
872 Err(e) => {
873 self.errors.push(e);
874 Type::Verbatim(Default::default())
875 }
876 },
877 _ => fold::fold_type(self, ty),
878 }
879 }
880
881 fn fold_impl_item_method(&mut self, mut impl_item_method: ImplItemMethod) -> ImplItemMethod {
882 let has_self = impl_item_method
883 .sig
884 .inputs
885 .first()
886 .map(|a| match a {
887 FnArg::Receiver(_) => true,
888 _ => false,
889 })
890 .unwrap_or(false);
891
892 impl_item_method.sig = fold::fold_signature(self, impl_item_method.sig);
893
894 let old_has_self_parameter = self.has_self_parameter;
896 self.has_self_parameter = has_self;
897
898 impl_item_method.block = fold::fold_block(self, impl_item_method.block);
899 self.has_self_parameter = old_has_self_parameter;
900
901 impl_item_method
902 }
903}
904
905fn extract_tuple_placeholder_ident(trait_impl: &ItemImpl) -> Result<(bool, Ident)> {
907 match *trait_impl.self_ty {
908 Type::Reference(ref type_ref) => {
909 if let Type::Path(ref type_path) = *type_ref.elem {
910 if let Some(ident) = type_path.path.get_ident() {
911 return Ok((true, ident.clone()));
912 }
913 }
914 }
915 Type::Path(ref type_path) => {
916 if let Some(ident) = type_path.path.get_ident() {
917 return Ok((false, ident.clone()));
918 }
919 }
920 _ => {}
921 }
922
923 Err(Error::new(
924 trait_impl.self_ty.span(),
925 "Expected an `Ident` as tuple placeholder.",
926 ))
927}
928
929pub fn semi_automatic_impl(
931 trait_impl: ItemImpl,
932 tuple_elements: Vec<Ident>,
933 min: Option<usize>,
934) -> Result<TokenStream> {
935 let placeholder_ident = extract_tuple_placeholder_ident(&trait_impl)?;
936
937 let mut res = TokenStream::new();
938
939 (min.unwrap_or(0)..=tuple_elements.len()).try_for_each(|i| {
940 res.extend(ToTupleImplementation::generate_implementation(
941 &trait_impl,
942 &placeholder_ident.1,
943 &tuple_elements[..i],
944 placeholder_ident.0,
945 )?);
946 Ok::<_, Error>(())
947 })?;
948
949 Ok(res)
950}