1use super::{
2 attribute_parsing::{MethodWithAttrs, SabiTraitAttrs},
3 impl_interfacetype::{TraitStruct, WhichTrait, TRAIT_LIST},
4 lifetime_unelider::BorrowKind,
5 parse_utils::{parse_str_as_ident, parse_str_as_trait_bound, parse_str_as_type},
6 replace_self_path::{self, ReplaceWith},
7 *,
8};
9
10use crate::{
11 set_span_visitor::SetSpanVisitor,
12 utils::{dummy_ident, LinearResult, SynResultExt},
13};
14
15use as_derive_utils::{return_spanned_err, spanned_err, syn_err};
16
17use std::{
18 collections::{HashMap, HashSet},
19 iter,
20};
21
22use core_extensions::{matches, IteratorExt};
23
24use syn::{
25 punctuated::Punctuated,
26 spanned::Spanned,
27 token::Unsafe,
28 token::{Colon, Comma, Semi},
29 visit_mut::VisitMut,
30 Abi, Attribute, Block, FnArg, Ident, ItemTrait, Lifetime, LifetimeDef, TraitItem,
31 TypeParamBound, WherePredicate,
32};
33
34use proc_macro2::Span;
35
36#[derive(Debug, Clone)]
37pub struct AssocTyWithIndex {
38 pub index: usize,
39 pub assoc_ty: syn::TraitItemType,
40}
41
42#[derive(Debug, Clone)]
46pub(crate) struct TraitDefinition<'a> {
47 pub(crate) item: &'a ItemTrait,
48 pub(crate) name: &'a Ident,
50 pub(crate) which_object: WhichObject,
52 pub(crate) where_preds: Punctuated<WherePredicate, Comma>,
55 pub(crate) derive_attrs: &'a [Attribute],
57 pub(crate) other_attrs: &'a [Attribute],
59 pub(crate) generics: &'a syn::Generics,
60 pub(crate) iterator_item: Option<&'a syn::Type>,
63 #[allow(dead_code)]
64 pub(crate) deserialize_bound: Option<DeserializeBound>,
67 pub(crate) impld_traits: Vec<TraitImplness<'a>>,
69 pub(crate) unimpld_traits: Vec<&'a Ident>,
71 pub(crate) trait_flags: TraitStruct<bool>,
74 pub(crate) trait_spans: TraitStruct<Span>,
77 pub(crate) lifetime_bounds: Punctuated<&'a Lifetime, Comma>,
81 pub(crate) vis: VisibilityKind<'a>,
83 pub(crate) submod_vis: RelativeVis<'a>,
85 pub(crate) assoc_tys: HashMap<&'a Ident, AssocTyWithIndex>,
87 pub(crate) methods: Vec<TraitMethod<'a>>,
89 pub(crate) has_mut_methods: bool,
91 pub(crate) has_val_methods: bool,
93 pub(crate) disable_trait_impl: bool,
95 pub(crate) is_static: IsStaticTrait,
97 pub(crate) ts_fq_self: &'a TokenStream2,
99 pub(crate) ctokens: &'a CommonTokens,
100}
101
102impl<'a> TraitDefinition<'a> {
105 pub(super) fn new(
106 trait_: &'a ItemTrait,
107 SabiTraitAttrs {
108 attrs,
109 methods_with_attrs,
110 which_object,
111 disable_trait_impl,
112 disable_inherent_default,
113 ..
114 }: SabiTraitAttrs<'a>,
115 arenas: &'a Arenas,
116 ctokens: &'a CommonTokens,
117 ) -> Result<Self, syn::Error> {
118 let vis = VisibilityKind::new(&trait_.vis);
119 let submod_vis = vis.submodule_level(1);
120 let mut assoc_tys = HashMap::default();
121 let mut methods = Vec::<TraitMethod<'a>>::new();
122
123 let mut errors = LinearResult::ok(());
124
125 methods_with_attrs
126 .into_iter()
127 .zip(disable_inherent_default)
128 .filter_map(|(func, disable_inh_def)| {
129 match TraitMethod::new(func, disable_inh_def, ctokens, arenas) {
130 Ok(x) => x,
131 Err(e) => {
132 errors.push_err(e);
133 None
134 }
135 }
136 })
137 .extending(&mut methods);
138
139 let mut is_static = IsStaticTrait::No;
143
144 let lifetime_params: HashSet<&'a Lifetime> = trait_
145 .generics
146 .lifetimes()
147 .map(|l| &l.lifetime)
148 .chain(iter::once(&ctokens.static_lifetime))
149 .collect();
150
151 let GetSupertraits {
152 impld_traits,
153 unimpld_traits,
154 mut lifetime_bounds,
155 iterator_item,
156 deserialize_bound,
157 trait_flags,
158 trait_spans,
159 errors: supertrait_errors,
160 } = get_supertraits(
161 &trait_.supertraits,
162 &lifetime_params,
163 which_object,
164 arenas,
165 ctokens,
166 );
167 errors.combine_err(supertrait_errors.into());
168
169 for method in &methods {
175 if let SelfParam::ByRef {
176 lifetime: Some(lt), ..
177 } = method.self_param
178 {
179 if lifetime_params.contains(lt) {
180 lifetime_bounds.push(lt);
181 }
182 }
183 }
184
185 for lt in &lifetime_bounds {
186 if lt.ident == "static" {
187 is_static = IsStaticTrait::Yes;
188 }
189 }
190 let mut assoc_ty_index = 0;
193 for item in &trait_.items {
194 match item {
195 TraitItem::Method { .. } => {}
196 TraitItem::Type(assoc_ty) => {
197 let with_index = AssocTyWithIndex {
198 index: assoc_ty_index,
199 assoc_ty: assoc_ty.clone(),
200 };
201 assoc_tys.insert(&assoc_ty.ident, with_index);
202
203 assoc_ty_index += 1;
204 }
205 item => errors.push_err(spanned_err!(
206 item,
207 "Associated item not compatible with #[sabi_trait]",
208 )),
209 }
210 }
211
212 let has_mut_methods = methods.iter().any(|m| {
213 matches!(
214 &m.self_param,
215 SelfParam::ByRef {
216 is_mutable: true,
217 ..
218 }
219 )
220 });
221
222 let has_val_methods = methods
223 .iter()
224 .any(|m| matches!(&m.self_param, SelfParam::ByVal));
225
226 let ts_fq_self = {
227 let (_, generics_params, _) = trait_.generics.split_for_impl();
228 quote!( <_OrigPtr::PtrTarget as __Trait #generics_params >:: )
229 };
230
231 errors.into_result()?;
232
233 Ok(TraitDefinition {
234 item: trait_,
235 name: &trait_.ident,
236 which_object,
237 where_preds: trait_
238 .generics
239 .where_clause
240 .as_ref()
241 .map(|wc| wc.predicates.clone())
242 .unwrap_or_default(),
243 derive_attrs: arenas.alloc(attrs.derive_attrs),
244 other_attrs: arenas.alloc(attrs.other_attrs),
245 generics: &trait_.generics,
246 lifetime_bounds,
247 iterator_item,
248 deserialize_bound,
249 impld_traits,
250 unimpld_traits,
251 trait_flags,
252 trait_spans,
253 vis,
254 submod_vis,
255 assoc_tys,
256 methods,
257 has_mut_methods,
258 has_val_methods,
259 disable_trait_impl,
260 ts_fq_self: arenas.alloc(ts_fq_self),
261 is_static,
262 ctokens,
263 })
264 }
265
266 pub fn replace_self(&self, which_item: WhichItem) -> Result<Self, syn::Error> {
269 let mut this = self.clone();
270
271 let ctokens = self.ctokens;
272
273 let mut errors = LinearResult::ok(());
274
275 let replace_with = match which_item {
276 WhichItem::Trait | WhichItem::TraitImpl => {
277 return Ok(this);
278 }
279 WhichItem::TraitObjectImpl => ReplaceWith::Remove,
280 WhichItem::VtableDecl => ReplaceWith::Remove,
281 WhichItem::VtableImpl => ReplaceWith::Ident(ctokens.u_capself.clone()),
282 };
283
284 let is_assoc_type = |ident: &Ident| {
285 if self.assoc_tys.contains_key(ident) {
286 Some(ReplaceWith::Keep)
287 } else {
288 None
289 }
290 };
291
292 for where_pred in &mut this.where_preds {
293 replace_self_path::replace_self_path(where_pred, replace_with.clone(), is_assoc_type)
294 .combine_into_err(&mut errors);
295 }
296
297 for assoc_ty in this.assoc_tys.values_mut() {
298 replace_self_path::replace_self_path(
299 &mut assoc_ty.assoc_ty,
300 replace_with.clone(),
301 is_assoc_type,
302 )
303 .combine_into_err(&mut errors);
304 }
305
306 for method in &mut this.methods {
307 method
308 .replace_self(replace_with.clone(), is_assoc_type)
309 .combine_into_err(&mut errors);
310 }
311 errors.into_result().map(|_| this)
312 }
313
314 pub fn generics_tokenizer(
329 &self,
330 in_what: InWhat,
331 with_assoc_tys: WithAssocTys,
332 after_lifetimes: &'a TokenStream2,
333 ) -> GenericsTokenizer<'_> {
334 let ctokens = self.ctokens;
335 GenericsTokenizer {
336 gen_params_in: GenParamsIn::with_after_lifetimes(
337 self.generics,
338 in_what,
339 after_lifetimes,
340 ),
341 assoc_tys: match with_assoc_tys {
342 WithAssocTys::Yes(WhichSelf::Regular) => {
343 Some((&self.assoc_tys, &ctokens.ts_self_colon2))
344 }
345 WithAssocTys::Yes(WhichSelf::Underscore) => {
346 Some((&self.assoc_tys, &ctokens.ts_uself_colon2))
347 }
348 WithAssocTys::Yes(WhichSelf::FullyQualified) => {
349 Some((&self.assoc_tys, self.ts_fq_self))
350 }
351 WithAssocTys::Yes(WhichSelf::NoSelf) => Some((&self.assoc_tys, &ctokens.empty_ts)),
352 WithAssocTys::No => None,
353 },
354 }
355 }
356
357 pub fn erased_ptr_preds(&self) -> &'a TokenStream2 {
362 let ctokens = self.ctokens;
363 match (self.has_mut_methods, self.has_val_methods) {
364 (false, false) => &ctokens.ptr_ref_bound,
365 (false, true) => &ctokens.ptr_ref_val_bound,
366 (true, false) => &ctokens.ptr_mut_bound,
367 (true, true) => &ctokens.ptr_mut_val_bound,
368 }
369 }
370
371 pub fn trait_impl_where_preds(&self) -> Result<Punctuated<WherePredicate, Comma>, syn::Error> {
374 let mut where_preds = self.where_preds.clone();
375 let mut errors = LinearResult::ok(());
376 for where_pred in &mut where_preds {
377 replace_self_path::replace_self_path(where_pred, ReplaceWith::Remove, |ident| {
378 self.assoc_tys.get(ident).map(|_| ReplaceWith::Remove)
379 })
380 .combine_into_err(&mut errors);
381 }
382 errors.into_result().map(|_| where_preds)
383 }
384
385 pub fn methods_tokenizer(&self, which_item: WhichItem) -> MethodsTokenizer<'_> {
387 MethodsTokenizer {
388 trait_def: self,
389 which_item,
390 }
391 }
392}
393
394#[derive(Debug, Clone)]
398pub(crate) struct TraitMethod<'a> {
399 pub(crate) disable_inherent_default: bool,
400 pub(crate) unsafety: Option<&'a Unsafe>,
401 pub(crate) abi: Option<&'a Abi>,
402 pub(crate) derive_attrs: &'a [Attribute],
404 pub(crate) other_attrs: &'a [Attribute],
406 pub(crate) name: &'a Ident,
408 pub(crate) self_param: SelfParam<'a>,
409 pub(crate) lifetimes: Vec<&'a LifetimeDef>,
411 pub(crate) params: Vec<MethodParam<'a>>,
412 pub(crate) output: Option<syn::Type>,
414
415 pub(crate) return_borrow_kind: Option<BorrowKind>,
417
418 pub(crate) where_clause: MethodWhereClause<'a>,
419 pub(crate) default: Option<DefaultMethod<'a>>,
421 pub(crate) semicolon: Option<&'a Semi>,
424}
425
426#[derive(Debug, Clone)]
427pub(crate) struct DefaultMethod<'a> {
428 pub(crate) block: &'a Block,
429}
430
431#[derive(Debug, Clone, PartialEq, Eq)]
432pub(crate) struct MethodParam<'a> {
433 pub(crate) name: &'a Ident,
437 pub(crate) ty: syn::Type,
439 pub(crate) pattern: &'a syn::Pat,
441}
442
443impl<'a> TraitMethod<'a> {
444 pub fn new(
445 mwa: MethodWithAttrs<'a>,
446 disable_inherent_default: bool,
447 ctokens: &'a CommonTokens,
448 arena: &'a Arenas,
449 ) -> Result<Option<Self>, syn::Error> {
450 let method_signature = &mwa.item.sig;
451 let decl = method_signature;
452 let name = &method_signature.ident;
453
454 let mut errors = LinearResult::ok(());
455
456 let push_error_msg = |errors: &mut Result<(), syn::Error>| {
457 errors.push_err(spanned_err!(
458 method_signature.ident,
459 "Cannot define #[sabi_trait]traits containing methods \
460 without a `self`/`&self`/`&mut self` receiver (static methods)."
461 ));
462 };
463 if decl.inputs.is_empty() {
464 push_error_msg(&mut errors);
465 }
466
467 let mut input_iter = decl.inputs.iter();
468
469 let mut self_param = match input_iter.next() {
470 Some(FnArg::Receiver(receiver)) => match &receiver.reference {
471 Some((_, lifetime)) => SelfParam::ByRef {
472 lifetime: lifetime.as_ref(),
473 is_mutable: receiver.mutability.is_some(),
474 },
475 None => SelfParam::ByVal,
476 },
477 Some(FnArg::Typed { .. }) => {
478 push_error_msg(&mut errors);
479 SelfParam::ByVal
480 }
481 None => {
482 push_error_msg(&mut errors);
483 return errors.into_result().map(|_| unreachable!());
484 }
485 };
486
487 let mut lifetimes: Vec<&'a syn::LifetimeDef> = decl.generics.lifetimes().collect();
488
489 let mut return_borrow_kind = None::<BorrowKind>;
490
491 let output = match &decl.output {
492 syn::ReturnType::Default => None,
493 syn::ReturnType::Type(_, ty) => {
494 let mut ty: syn::Type = (**ty).clone();
495 if let SelfParam::ByRef { lifetime, .. } = &mut self_param {
496 let visit_data = LifetimeUnelider::new(lifetime).visit_type(&mut ty);
497
498 return_borrow_kind = visit_data.found_borrow_kind;
499
500 if let Some(lt) = visit_data.additional_lifetime_def {
501 lifetimes.push(lt);
502 }
503 }
504 Some(ty)
505 }
506 };
507
508 let default = mwa
509 .item
510 .default
511 .as_ref()
512 .map(|block| DefaultMethod { block });
513
514 let where_clause = decl
515 .generics
516 .where_clause
517 .as_ref()
518 .and_then(|wc| match MethodWhereClause::new(wc, ctokens) {
519 Ok(x) => Some(x),
520 Err(e) => {
521 errors.push_err(e);
522 None
523 }
524 })
525 .unwrap_or_default();
526
527 let mut params = Vec::<MethodParam<'a>>::with_capacity(input_iter.len());
528
529 for (param_i, param) in input_iter.enumerate() {
530 let (pattern, ty) = match param {
531 FnArg::Receiver { .. } => unreachable!(),
532 FnArg::Typed(typed) => (&*typed.pat, &*typed.ty),
533 };
534
535 let name = format!("param_{}", param_i);
536 let mut name = syn::parse_str::<Ident>(&name).unwrap_or_else(|e| {
537 errors.push_err(e);
538 dummy_ident()
539 });
540 name.set_span(param.span());
541
542 params.push(MethodParam {
543 name: arena.alloc(name),
544 ty: ty.clone(),
545 pattern,
546 });
547 }
548
549 errors.into_result()?;
550
551 Ok(Some(Self {
552 disable_inherent_default,
553 unsafety: method_signature.unsafety.as_ref(),
554 abi: method_signature.abi.as_ref(),
555 derive_attrs: arena.alloc(mwa.attrs.derive_attrs),
556 other_attrs: arena.alloc(mwa.attrs.other_attrs),
557 name,
558 lifetimes,
559 self_param,
560 params,
561 output,
562 return_borrow_kind,
563 where_clause,
564 default,
565 semicolon: mwa.item.semi_token.as_ref(),
566 }))
567 }
568
569 pub fn replace_self<F>(
575 &mut self,
576 replace_with: ReplaceWith,
577 mut is_assoc_type: F,
578 ) -> Result<(), syn::Error>
579 where
580 F: FnMut(&Ident) -> Option<ReplaceWith>,
581 {
582 let mut errors = LinearResult::ok(());
583
584 for param in self
585 .params
586 .iter_mut()
587 .map(|x| &mut x.ty)
588 .chain(self.output.as_mut())
589 {
590 replace_self_path::replace_self_path(param, replace_with.clone(), &mut is_assoc_type)
591 .combine_into_err(&mut errors);
592 }
593 errors.into()
594 }
595}
596
597#[derive(Debug, Copy, Clone)]
602pub struct GenericsTokenizer<'a> {
603 gen_params_in: GenParamsIn<'a, &'a TokenStream2>,
604 assoc_tys: Option<(&'a HashMap<&'a Ident, AssocTyWithIndex>, &'a TokenStream2)>,
605}
606
607impl<'a> GenericsTokenizer<'a> {
608 #[allow(dead_code)]
610 pub fn set_unsized_types(&mut self) {
611 self.gen_params_in.set_unsized_types();
612 }
613 pub fn set_no_bounds(&mut self) {
615 self.gen_params_in.set_no_bounds();
616 }
617 pub fn skip_lifetimes(&mut self) {
618 self.gen_params_in.skip_lifetimes();
619 }
620 #[allow(dead_code)]
621 pub fn skip_consts(&mut self) {
622 self.gen_params_in.skip_consts();
623 }
624}
625
626impl<'a> ToTokens for GenericsTokenizer<'a> {
627 fn to_tokens(&self, ts: &mut TokenStream2) {
628 let with_bounds = self.gen_params_in.outputs_bounds();
629 let with_default = self.gen_params_in.in_what == InWhat::ItemDecl;
630
631 let unsized_types = self.gen_params_in.are_types_unsized();
632
633 let in_dummy_struct = self.gen_params_in.in_what == InWhat::DummyStruct;
634
635 let skips_unbounded = self.gen_params_in.skips_unbounded();
636
637 self.gen_params_in.to_tokens(ts);
638 if let Some((assoc_tys, self_tokens)) = self.assoc_tys {
639 for with_index in assoc_tys.values() {
640 let assoc_ty = &with_index.assoc_ty;
641
642 if skips_unbounded && assoc_ty.bounds.is_empty() {
643 continue;
644 }
645
646 self_tokens.to_tokens(ts);
647
648 if in_dummy_struct {
649 use syn::token::{Const, Star};
650 Star::default().to_tokens(ts);
651 Const::default().to_tokens(ts);
652 }
653
654 assoc_ty.ident.to_tokens(ts);
655
656 let colon_token = assoc_ty.colon_token.filter(|_| with_bounds);
657
658 if unsized_types {
659 if colon_token.is_none() {
660 Colon::default().to_tokens(ts);
661 }
662 quote!(?Sized+).to_tokens(ts);
663 }
664 if let Some(colon_token) = colon_token {
665 colon_token.to_tokens(ts);
666 assoc_ty.bounds.to_tokens(ts);
667 }
668
669 match &assoc_ty.default {
670 Some((eq_token, default_ty)) if with_default => {
671 eq_token.to_tokens(ts);
672 default_ty.to_tokens(ts);
673 }
674 _ => {}
675 }
676
677 Comma::default().to_tokens(ts);
678 }
679 }
680 }
681}
682
683#[derive(Debug, Clone)]
687pub(crate) struct DeserializeBound;
688
689struct GetSupertraits<'a> {
691 impld_traits: Vec<TraitImplness<'a>>,
692 unimpld_traits: Vec<&'a Ident>,
693 lifetime_bounds: Punctuated<&'a Lifetime, Comma>,
694 iterator_item: Option<&'a syn::Type>,
695 deserialize_bound: Option<DeserializeBound>,
696 trait_flags: TraitStruct<bool>,
697 trait_spans: TraitStruct<Span>,
698 errors: LinearResult<()>,
699}
700
701#[derive(Debug, Clone)]
703pub(crate) struct TraitImplness<'a> {
704 pub(crate) ident: Ident,
705 pub(crate) bound: syn::TraitBound,
706 pub(crate) is_implemented: bool,
707 pub(crate) _marker: PhantomData<&'a ()>,
708}
709
710fn get_supertraits<'a, I>(
712 supertraits: I,
713 lifetime_params: &HashSet<&'a Lifetime>,
714 which_object: WhichObject,
715 arenas: &'a Arenas,
716 _ctokens: &'a CommonTokens,
717) -> GetSupertraits<'a>
718where
719 I: IntoIterator<Item = &'a TypeParamBound>,
720{
721 let trait_map = TRAIT_LIST
722 .iter()
723 .map(|t| (parse_str_as_ident(t.name), t.which_trait))
724 .collect::<HashMap<Ident, WhichTrait>>();
725
726 let mut trait_struct = TraitStruct::TRAITS.map(|_, t| TraitImplness {
729 ident: parse_str_as_ident(t.name),
730 bound: parse_str_as_trait_bound(t.full_path).expect("BUG"),
731 is_implemented: false,
732 _marker: PhantomData,
733 });
734
735 let mut lifetime_bounds = Punctuated::<&'a Lifetime, Comma>::new();
736 let mut iterator_item = None;
737 let mut errors = LinearResult::ok(());
738 let deserialize_bound = None;
739
740 for supertrait_bound in supertraits {
741 match supertrait_bound {
742 TypeParamBound::Trait(trait_bound) => {
743 let last_path_component = match trait_bound.path.segments.last() {
744 Some(x) => x,
745 None => continue,
746 };
747 let trait_ident = &last_path_component.ident;
748
749 match trait_map.get(trait_ident) {
750 Some(&which_trait) => {
751 let usable_by = which_trait.usable_by();
752 match which_object {
753 WhichObject::DynTrait if !usable_by.dyn_trait() => {
754 errors.push_err(spanned_err!(
755 trait_bound.path,
756 "cannot use this trait with DynTrait",
757 ));
758 }
759 WhichObject::RObject if !usable_by.robject() => {
760 errors.push_err(spanned_err!(
761 trait_bound.path,
762 "cannot use this trait with RObject.
763 To make that trait usable you must use the \
764 #[sabi(use_dyntrait)] attribute,\
765 which changes the trait object implementation \
766 from using RObject to using DynTrait.\n\
767 ",
768 ));
769 }
770 WhichObject::DynTrait | WhichObject::RObject => {}
771 }
772
773 fn set_impld(wtrait: &mut TraitImplness<'_>, span: Span) {
774 wtrait.is_implemented = true;
775 wtrait.ident.set_span(span);
776 SetSpanVisitor::new(span).visit_trait_bound_mut(&mut wtrait.bound);
777 }
778
779 let span = trait_bound.span();
780
781 set_impld(&mut trait_struct[which_trait], span);
782
783 match which_trait {
784 WhichTrait::Iterator | WhichTrait::DoubleEndedIterator => {
785 set_impld(&mut trait_struct.iterator, span);
786
787 let iter_item = extract_iterator_item(last_path_component, arenas);
788 iterator_item = iterator_item.or(iter_item);
789 }
790 WhichTrait::Deserialize => {
791 errors.push_err(spanned_err!(
792 trait_bound.path,
793 "Deserialize is not currently supported."
794 ));
795 }
796 WhichTrait::Serialize => {
797 errors.push_err(spanned_err!(
798 trait_bound.path,
799 "Serialize is not currently supported."
800 ));
801 }
802 WhichTrait::Eq | WhichTrait::PartialOrd => {
803 set_impld(&mut trait_struct.partial_eq, span);
804 }
805 WhichTrait::Ord => {
806 set_impld(&mut trait_struct.partial_eq, span);
807 set_impld(&mut trait_struct.eq, span);
808 set_impld(&mut trait_struct.partial_ord, span);
809 }
810 WhichTrait::IoBufRead => {
811 set_impld(&mut trait_struct.io_read, span);
812 }
813 WhichTrait::Error => {
814 set_impld(&mut trait_struct.display, span);
815 set_impld(&mut trait_struct.debug, span);
816 }
817 _ => {}
818 }
819 }
820 None => {
821 let list = trait_map
822 .keys()
823 .map(|x| x.to_string())
824 .collect::<Vec<String>>();
825
826 errors.push_err(spanned_err!(
827 supertrait_bound,
828 "Unexpected supertrait bound.\nExpected one of:\n{}",
829 list.join("/"),
830 ));
831 break;
832 }
833 }
834 }
835 TypeParamBound::Lifetime(lt) => {
836 if lifetime_params.contains(lt) {
837 lifetime_bounds.push(lt);
838 } else {
839 errors.push_err(spanned_err!(
840 lt,
841 "Lifetimes is not from the trait or `'static`.",
842 ));
843 break;
844 }
845 }
846 };
847 }
848
849 let iter_trait = &mut trait_struct.iterator;
850 let de_iter_trait = &mut trait_struct.double_ended_iterator;
851 if iter_trait.is_implemented || de_iter_trait.is_implemented {
852 let iter_item: syn::Type = iterator_item.cloned().unwrap_or_else(|| {
853 let span = if de_iter_trait.is_implemented {
854 de_iter_trait.ident.span()
855 } else {
856 iter_trait.ident.span()
857 };
858 errors.push_err(syn_err!(span, "You must specify the Iterator item type."));
859 parse_str_as_type("()").expect("BUG")
860 });
861 let path_args = type_as_iter_path_arguments(iter_item);
862
863 fn set_last_arguments(bounds: &mut syn::TraitBound, path_args: syn::PathArguments) {
864 bounds.path.segments.last_mut().expect("BUG").arguments = path_args;
865 }
866
867 if de_iter_trait.is_implemented {
868 set_last_arguments(&mut de_iter_trait.bound, path_args.clone());
869 }
870 set_last_arguments(&mut iter_trait.bound, path_args);
871 }
872
873 let mut impld_traits = Vec::new();
874 let mut unimpld_traits = Vec::new();
875 let trait_flags = trait_struct.as_ref().map(|_, x| x.is_implemented);
876 let trait_spans = trait_struct.as_ref().map(|_, x| x.ident.span());
877
878 for trait_ in trait_struct.to_vec() {
879 if trait_.is_implemented {
880 impld_traits.push(trait_);
881 } else {
882 unimpld_traits.push(arenas.alloc(trait_.ident.clone()));
883 }
884 }
885
886 GetSupertraits {
887 impld_traits,
888 unimpld_traits,
889 lifetime_bounds,
890 iterator_item,
891 deserialize_bound,
892 trait_flags,
893 trait_spans,
894 errors,
895 }
896}
897
898fn extract_iterator_item<'a>(
902 last_path_component: &syn::PathSegment,
903 arenas: &'a Arenas,
904) -> Option<&'a syn::Type> {
905 use syn::{GenericArgument, PathArguments};
906
907 let angle_brackets = match &last_path_component.arguments {
908 PathArguments::AngleBracketed(x) => x,
909 _ => return None,
910 };
911
912 for gen_arg in &angle_brackets.args {
913 match gen_arg {
914 GenericArgument::Binding(bind) if bind.ident == "Item" => {
915 return Some(arenas.alloc(bind.ty.clone()));
916 }
917 _ => {}
918 }
919 }
920 None
921}
922
923fn type_as_iter_path_arguments(ty: syn::Type) -> syn::PathArguments {
925 let x = syn::Binding {
926 ident: parse_str_as_ident("Item"),
927 eq_token: Default::default(),
928 ty,
929 };
930
931 let x = syn::GenericArgument::Binding(x);
932
933 let x = syn::AngleBracketedGenericArguments {
934 colon2_token: None,
935 lt_token: Default::default(),
936 args: iter::once(x).collect(),
937 gt_token: Default::default(),
938 };
939
940 syn::PathArguments::AngleBracketed(x)
941}
942
943#[allow(dead_code)]
945fn extract_deserialize_lifetime<'a>(
946 last_path_component: &syn::PathSegment,
947 arenas: &'a Arenas,
948) -> Result<&'a syn::Lifetime, syn::Error> {
949 use syn::{GenericArgument, PathArguments};
950
951 let angle_brackets = match &last_path_component.arguments {
952 PathArguments::AngleBracketed(x) => x,
953 _ => return_spanned_err!(last_path_component, "Expected a lifetime parameter inside"),
954 };
955
956 for gen_arg in &angle_brackets.args {
957 if let GenericArgument::Lifetime(lt) = gen_arg {
958 return Ok(arenas.alloc(lt.clone()));
959 }
960 }
961 Err(spanned_err!(
962 last_path_component,
963 "Expected a lifetime parameter inside"
964 ))
965}