1#![doc = include_str!("./README.md")]
2
3use petgraph::graph::{DefaultIx, NodeIndex};
4use petgraph::visit::EdgeRef;
5use petgraph::Graph;
6use proc_macro2::Span;
7use std::collections::{HashMap, HashSet};
8use syn::parse::Parse;
9use syn::spanned::Spanned;
10use syn::visit::Visit;
11use syn::visit_mut::VisitMut;
12use syn::*;
13use template_quote::{quote, ToTokens};
14
15pub use syn;
16
17pub struct Leaker {
19 generics: Generics,
21 graph: Graph<Type, ()>,
22 map: HashMap<Type, NodeIndex<DefaultIx>>,
23 must_intern_nodes: HashSet<NodeIndex<DefaultIx>>,
24 root_nodes: HashSet<NodeIndex<DefaultIx>>,
25 pub implementor_type_fn: Box<dyn Fn(PathArguments) -> Type>,
30}
31
32#[derive(Debug, Clone)]
34pub struct NotInternableError(pub Span);
35
36impl std::fmt::Display for NotInternableError {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.write_str("Not internable")
39 }
40}
41
42impl std::error::Error for NotInternableError {}
43
44pub fn encode_generics_to_ty<'a>(iter: impl IntoIterator<Item = &'a GenericArgument>) -> Type {
46 Type::Tuple(TypeTuple {
47 paren_token: Default::default(),
48 elems: iter
49 .into_iter()
50 .map(|param| -> Type {
51 match param {
52 GenericArgument::Lifetime(lifetime) => {
53 parse_quote!(& #lifetime ())
54 }
55 GenericArgument::Const(expr) => {
56 parse_quote!([(); #expr as usize])
57 }
58 GenericArgument::Type(ty) => ty.clone(),
59 _ => panic!(),
60 }
61 })
62 .collect(),
63 })
64}
65
66#[derive(Clone, Debug)]
68pub enum CheckResult {
69 MustIntern(Span),
71 MustInternOrInherit(Span),
74 MustNotIntern(Span),
77 Neutral,
79}
80
81struct AnalyzeVisitor<'a> {
82 leaker: &'a mut Leaker,
83 generics: Generics,
84 parent: Option<NodeIndex<DefaultIx>>,
85 error: Option<Span>,
86}
87
88impl<'a, 'ast> Visit<'ast> for AnalyzeVisitor<'a> {
89 fn visit_trait_item_fn(&mut self, i: &TraitItemFn) {
90 let mut visitor = AnalyzeVisitor {
91 leaker: &mut self.leaker,
92 generics: self.generics.clone(),
93 parent: self.parent.clone(),
94 error: self.error.clone(),
95 };
96 for g in &i.sig.generics.params {
97 visitor.generics.params.push(g.clone());
98 }
99 let mut i = i.clone();
100 i.default = None;
101 i.semi_token = Some(Default::default());
102 syn::visit::visit_trait_item_fn(&mut visitor, &mut i);
103 self.error = visitor.error;
104 }
105
106 fn visit_trait_item_type(&mut self, i: &TraitItemType) {
107 let mut visitor = AnalyzeVisitor {
108 leaker: &mut self.leaker,
109 generics: self.generics.clone(),
110 parent: self.parent.clone(),
111 error: self.error.clone(),
112 };
113 for g in &i.generics.params {
114 visitor.generics.params.push(g.clone());
115 }
116 syn::visit::visit_trait_item_type(&mut visitor, i);
117 self.error = visitor.error;
118 }
119
120 fn visit_type(&mut self, i: &Type) {
121 match self.leaker.check(&self.generics, i) {
122 Err((_, s)) | Ok(CheckResult::MustNotIntern(s)) => {
123 self.error = Some(s);
125 }
126 o => {
127 let child = self
128 .leaker
129 .map
130 .entry(i.clone())
131 .or_insert_with(|| self.leaker.graph.add_node(i.clone()))
132 .clone();
133 if let Some(parent) = &self.parent {
134 self.leaker
135 .graph
136 .add_edge(parent.clone(), child.clone(), ());
137 } else {
138 self.leaker.root_nodes.insert(child.clone());
139 }
140 if let Ok(CheckResult::MustIntern(_)) = o {
141 self.leaker.must_intern_nodes.insert(child.clone());
143 } else {
144 let parent = self.parent;
146 self.parent = Some(child);
147 syn::visit::visit_type(self, i);
148 self.parent = parent;
149 }
150 }
151 }
152 }
153
154 fn visit_trait_bound(&mut self, i: &TraitBound) {
155 if i.path.leading_colon.is_none() {
156 self.error = Some(i.span());
158 } else {
159 syn::visit::visit_trait_bound(self, i)
160 }
161 }
162
163 fn visit_expr_path(&mut self, i: &ExprPath) {
164 if i.path.leading_colon.is_none() {
165 self.error = Some(i.span());
167 } else {
168 syn::visit::visit_expr_path(self, i)
169 }
170 }
171}
172
173impl Leaker {
174 pub fn from_struct(input: &ItemStruct) -> std::result::Result<Self, NotInternableError> {
189 let name = input.ident.clone();
190 let mut leaker = Leaker::with_generics_and_implementor(
191 input.generics.clone(),
192 Box::new(move |args: PathArguments| parse_quote!(#name #args)),
193 );
194 let mut visitor = AnalyzeVisitor {
195 leaker: &mut leaker,
196 parent: None,
197 error: None,
198 generics: input.generics.clone(),
199 };
200 visitor.visit_item_struct(input);
201 if let Some(e) = visitor.error {
202 return Err(NotInternableError(e));
203 }
204 Ok(leaker)
205 }
206
207 pub fn from_enum(input: &ItemEnum) -> std::result::Result<Self, NotInternableError> {
209 let name = input.ident.clone();
210 let mut leaker = Self::with_generics_and_implementor(
211 input.generics.clone(),
212 Box::new(move |args: PathArguments| parse_quote!(#name #args)),
213 );
214 let mut visitor = AnalyzeVisitor {
215 leaker: &mut leaker,
216 parent: None,
217 error: None,
218 generics: input.generics.clone(),
219 };
220 visitor.visit_item_enum(input);
221 if let Some(e) = visitor.error {
222 return Err(NotInternableError(e));
223 }
224 Ok(leaker)
225 }
226
227 pub fn from_trait(
248 input: &ItemTrait,
249 implementor_type_fn: Box<dyn Fn(PathArguments) -> Type>,
250 ) -> std::result::Result<Self, NotInternableError> {
251 let mut leaker =
252 Self::with_generics_and_implementor(input.generics.clone(), implementor_type_fn);
253 let mut visitor = AnalyzeVisitor {
254 leaker: &mut leaker,
255 parent: None,
256 error: None,
257 generics: input.generics.clone(),
258 };
259 visitor.visit_item_trait(input);
260 if let Some(e) = visitor.error {
261 return Err(NotInternableError(e));
262 }
263 Ok(leaker)
264 }
265
266 pub fn with_generics_and_implementor(
271 generics: Generics,
272 implementor_type_fn: Box<dyn Fn(PathArguments) -> Type>,
273 ) -> Self {
274 Self {
275 generics,
276 graph: Graph::new(),
277 map: HashMap::new(),
278 must_intern_nodes: HashSet::new(),
279 root_nodes: HashSet::new(),
280 implementor_type_fn,
281 }
282 }
283
284 pub fn intern(
286 &mut self,
287 generics: Generics,
288 ty: &Type,
289 ) -> std::result::Result<&mut Self, NotInternableError> {
290 let mut visitor = AnalyzeVisitor {
291 leaker: self,
292 parent: None,
293 error: None,
294 generics,
295 };
296 visitor.visit_type(ty);
297 if let Some(e) = visitor.error {
298 Err(NotInternableError(e))
299 } else {
300 Ok(self)
301 }
302 }
303
304 pub fn check(
310 &self,
311 generics: &Generics,
312 ty: &Type,
313 ) -> std::result::Result<CheckResult, (Span, Span)> {
314 use syn::visit::Visit;
315 #[derive(Clone)]
316 struct Visitor {
317 generic_lifetimes: Vec<Lifetime>,
318 generic_idents: Vec<Ident>,
319 impossible: Option<Span>,
320 must: Option<(isize, Span)>,
321 }
322
323 const _: () = {
324 use syn::visit::Visit;
325 impl<'a> Visit<'a> for Visitor {
326 fn visit_type(&mut self, i: &Type) {
327 match i {
328 Type::BareFn(TypeBareFn {
329 lifetimes,
330 inputs,
331 output,
332 ..
333 }) => {
334 let mut visitor = self.clone();
335 visitor.must = None;
336 visitor.generic_lifetimes.extend(
337 lifetimes
338 .as_ref()
339 .map(|ls| {
340 ls.lifetimes.iter().map(|gp| {
341 if let GenericParam::Lifetime(lt) = gp {
342 lt.lifetime.clone()
343 } else {
344 panic!()
345 }
346 })
347 })
348 .into_iter()
349 .flatten(),
350 );
351 for input in inputs {
352 visitor.visit_type(&input.ty);
353 }
354 if let ReturnType::Type(_, output) = output {
355 visitor.visit_type(output.as_ref());
356 }
357 if self.impossible.is_none() {
358 self.impossible = visitor.impossible;
359 }
360 match (self.must.clone(), visitor.must.clone()) {
361 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
362 self.must = Some((v_l + 1, v_m))
363 }
364 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
365 _ => (),
366 }
367 return;
368 }
369 Type::TraitObject(TypeTraitObject { bounds, .. }) => {
370 for bound in bounds {
371 match bound {
372 TypeParamBound::Trait(TraitBound {
373 lifetimes, path, ..
374 }) => {
375 let mut visitor = self.clone();
376 visitor.must = None;
377 visitor.generic_lifetimes.extend(
378 lifetimes
379 .as_ref()
380 .map(|ls| {
381 ls.lifetimes.iter().map(|gp| {
382 if let GenericParam::Lifetime(lt) = gp {
383 lt.lifetime.clone()
384 } else {
385 panic!()
386 }
387 })
388 })
389 .into_iter()
390 .flatten(),
391 );
392 visitor.visit_path(path);
393 if self.impossible.is_none() {
394 self.impossible = visitor.impossible;
395 }
396 match (self.must.clone(), visitor.must.clone()) {
397 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
398 self.must = Some((v_l + 1, v_m))
399 }
400 (None, Some((v_l, v_m))) => {
401 self.must = Some((v_l + 1, v_m))
402 }
403 _ => (),
404 }
405 return;
406 }
407 TypeParamBound::Verbatim(_) => {
408 self.impossible = Some(bound.span());
409 return;
410 }
411 _ => (),
412 }
413 }
414 }
415 Type::ImplTrait(_) | Type::Macro(_) | Type::Verbatim(_) => {
416 self.impossible = Some(i.span());
417 }
418 _ => (),
419 }
420 let mut visitor = self.clone();
421 visitor.must = None;
422 syn::visit::visit_type(&mut visitor, i);
423 if visitor.impossible.is_some() {
424 self.impossible = visitor.impossible;
425 }
426 match (self.must.clone(), visitor.must.clone()) {
427 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
428 self.must = Some((v_l + 1, v_m))
429 }
430 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
431 _ => (),
432 }
433 }
434 fn visit_qself(&mut self, i: &QSelf) {
435 if i.as_token.is_none() {
436 self.impossible = Some(i.span());
437 }
438 syn::visit::visit_qself(self, i)
439 }
440 fn visit_lifetime(&mut self, i: &Lifetime) {
441 if i.to_string() != "'static"
442 && i.to_string() != "'_"
443 && !self.generic_lifetimes.iter().any(|lt| lt == i)
444 {
445 self.must = Some((-1, i.span()));
446 }
447 syn::visit::visit_lifetime(self, i)
448 }
449 fn visit_expr(&mut self, i: &Expr) {
450 match i {
451 Expr::Closure(_) | Expr::Assign(_) | Expr::Verbatim(_) | Expr::Macro(_) => {
452 self.impossible = Some(i.span());
453 }
454 _ => (),
455 }
456 syn::visit::visit_expr(self, i)
457 }
458 fn visit_path(&mut self, i: &Path) {
459 if matches!(i.segments.iter().next(), Some(PathSegment { ident, arguments }) if ident == "Self" && arguments.is_none())
460 {
461 } else {
463 match (i.leading_colon, i.get_ident()) {
464 (None, Some(ident))
466 if self.generic_idents.contains(&ident) || ident == "Self" => {}
467 (None, _) => {
469 self.must = Some((-1, i.span()));
470 }
471 (Some(_), _) => (),
473 }
474 }
475
476 syn::visit::visit_path(self, i)
477 }
478 }
479 };
480 let mut visitor = Visitor {
481 generic_lifetimes: generics
482 .params
483 .iter()
484 .filter_map(|gp| {
485 if let GenericParam::Lifetime(lt) = gp {
486 Some(lt.lifetime.clone())
487 } else {
488 None
489 }
490 })
491 .collect(),
492 generic_idents: generics
493 .params
494 .iter()
495 .filter_map(|gp| match gp {
496 GenericParam::Type(TypeParam { ident, .. })
497 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
498 _ => None,
499 })
500 .collect(),
501 impossible: None,
502 must: None,
503 };
504 visitor.visit_type(ty);
505 match (visitor.must, visitor.impossible) {
506 (None, None) => Ok(CheckResult::Neutral),
507 (Some((0, span)), None) => Ok(CheckResult::MustIntern(span)),
508 (Some((_, span)), None) => Ok(CheckResult::MustInternOrInherit(span)),
509 (None, Some(span)) => Ok(CheckResult::MustNotIntern(span)),
510 (Some((_, span0)), Some(span1)) => Err((span0, span1)),
511 }
512 }
513
514 pub fn finish(
516 self,
517 mut repeater_path_fn: impl FnMut(usize) -> Path,
518 ) -> (Vec<ItemImpl>, Referrer) {
519 let (impl_generics, _, where_clause) = self.generics.split_for_impl();
520 let id_map: HashMap<_, _> = self
521 .root_nodes
522 .iter()
523 .enumerate()
524 .map(|(n, idx)| {
525 (
526 self.graph.node_weight(idx.clone()).expect("hello3").clone(),
527 n,
528 )
529 })
530 .collect();
531 let path_args = PathArguments::AngleBracketed(AngleBracketedGenericArguments {
532 colon2_token: None,
533 lt_token: Token),
534 args: self
535 .generics
536 .params
537 .iter()
538 .map(|param| match param {
539 GenericParam::Lifetime(lifetime_param) => {
540 GenericArgument::Lifetime(lifetime_param.lifetime.clone())
541 }
542 GenericParam::Type(TypeParam { ident, .. }) => {
543 GenericArgument::Type(parse_quote!(#ident))
544 }
545 GenericParam::Const(ConstParam { ident, .. }) => {
546 GenericArgument::Const(parse_quote!(#ident))
547 }
548 })
549 .collect(),
550 gt_token: Token),
551 });
552 (
553 id_map
554 .iter()
555 .map(|(ty, n)| {
556 parse2(quote! {
557 impl #impl_generics #{repeater_path_fn(*n)} for #{(*self.implementor_type_fn)(path_args.clone())} #where_clause {
558 type Type = #ty;
559 }
560 }).expect("hello4")
561 })
562 .collect(),
563 Referrer { map: id_map },
564 )
565 }
566
567 #[cfg_attr(doc, aquamarine::aquamarine)]
568 pub fn reduce_roots(&mut self) {
637 self.reduce_unreachable_nodes();
639 }
643
644 fn reduce_obvious_nodes(&mut self) {
645 let mut must_intern_nodes: Vec<_> = self.must_intern_nodes.iter().cloned().collect();
646 let mut root_nodes: Vec<_> = self.root_nodes.iter().cloned().collect();
647 let nodes: Vec<_> = self
648 .graph
649 .node_indices()
650 .filter_map(|n| {
651 let mut it = self.graph.edges(n.clone());
652 if let Some(edge) = it.next() {
653 if let None = it.next() {
654 return Some((edge.source(), edge.target(), edge.id()));
655 }
656 }
657 None
658 })
659 .collect();
660 for (node1, node2, edge) in nodes {
661 self.graph.remove_edge(edge);
662 for (edge_in_source, edge_in) in self
663 .graph
664 .edges_directed(node1, petgraph::Direction::Incoming)
665 .map(|er| (er.source(), er.id()))
666 .collect::<Vec<_>>()
667 {
668 self.graph.update_edge(edge_in_source, node2, ());
669 self.graph.remove_edge(edge_in);
670 }
671 must_intern_nodes.iter_mut().for_each(|n| {
672 if n == &node1 {
673 *n = node2.clone()
674 }
675 });
676 root_nodes.iter_mut().for_each(|n| {
677 if n == &node1 {
678 *n = node2.clone()
679 }
680 });
681 self.graph.remove_node(node1);
682 }
683 self.must_intern_nodes = must_intern_nodes.into_iter().collect();
684 self.root_nodes = root_nodes.into_iter().collect();
685 }
686
687 fn reduce_unreachable_nodes(&mut self) {
688 let reachable_forward = get_reachable_nodes(&self.graph, self.root_nodes.iter().cloned());
689 self.graph.reverse();
690 let reachable_backward =
691 get_reachable_nodes(&self.graph, self.must_intern_nodes.iter().cloned());
692 self.graph.reverse();
693 let reachable = reachable_forward
694 .intersection(&reachable_backward)
695 .cloned()
696 .collect::<HashSet<_>>();
697 let mut new_graph = Graph::new();
705 let mut node_map = HashMap::new();
706 for node in self.graph.node_indices() {
707 if reachable.contains(&node) {
708 let new_node = new_graph.add_node(self.graph[node].clone());
709 node_map.insert(node, new_node);
710 }
711 }
712 for edge in self.graph.edge_indices() {
713 let (n1, n2) = self.graph.edge_endpoints(edge).unwrap();
714 if let (Some(nn1), Some(nn2)) = (node_map.get(&n1), node_map.get(&n2)) {
715 new_graph.add_edge(*nn1, *nn2, ());
716 }
717 }
718 self.root_nodes = self
719 .root_nodes
720 .iter()
721 .filter_map(|n| node_map.get(n).cloned())
722 .collect();
723 self.must_intern_nodes = self
724 .must_intern_nodes
725 .iter()
726 .filter_map(|n| node_map.get(n).cloned())
727 .collect();
728 let _ = std::mem::replace(&mut self.graph, new_graph);
729 }
730}
731
732fn get_reachable_nodes<N, E>(
733 graph: &Graph<N, E>,
734 roots: impl IntoIterator<Item = NodeIndex<DefaultIx>>,
735) -> HashSet<NodeIndex<DefaultIx>> {
736 let mut ret: HashSet<_> = roots.into_iter().collect();
737 let mut frontier = ret.clone();
738 loop {
739 let mut buf: HashSet<_> = frontier
740 .iter()
741 .map(|node| graph.neighbors(node.clone()))
742 .flatten()
743 .collect();
744 let mut count = 0;
745 for node in &buf {
746 if ret.insert(node.clone()) {
747 count += 1;
748 }
749 }
750 if count == 0 {
751 break;
752 }
753 std::mem::swap(&mut frontier, &mut buf);
754 }
755 ret
756}
757
758#[derive(Clone, PartialEq, Eq, Debug)]
759pub struct Referrer {
760 map: HashMap<Type, usize>,
761}
762
763impl Referrer {
764 pub fn is_empty(&self) -> bool {
765 self.map.is_empty()
766 }
767
768 pub fn iter(&self) -> impl Iterator<Item = &Type> {
769 self.map.keys()
770 }
771
772 pub fn into_visitor<F: FnMut(usize) -> Path + Clone>(
773 self,
774 leaker_ty: Type,
775 repeater_path_fn: F,
776 ) -> Visitor<F> {
777 Visitor(self, leaker_ty, repeater_path_fn)
778 }
779
780 pub fn expand(
781 &self,
782 ty: Type,
783 leaker_ty: &Type,
784 repeater_path_fn: impl FnMut(usize) -> Path,
785 ) -> Type {
786 use syn::fold::Fold;
787
788 struct Folder<'a, F>(&'a Referrer, &'a Type, F);
789 impl<'a, F: FnMut(usize) -> Path> Fold for Folder<'a, F> {
790 fn fold_type(&mut self, ty: Type) -> Type {
791 if let Some(idx) = self.0.map.get(&ty) {
792 parse2(quote! {
793 <#{&self.1} as #{&self.2(*idx)}>::Type
794 })
795 .unwrap()
796 } else {
797 syn::fold::fold_type(self, ty)
798 }
799 }
800 }
801 let mut folder = Folder(self, leaker_ty, repeater_path_fn);
802 folder.fold_type(ty)
803 }
804}
805
806#[derive(Clone, Debug)]
807pub struct Visitor<F>(Referrer, Type, F);
808
809impl<F: FnMut(usize) -> Path + Clone> Visitor<F> {
810 fn with_generics(&mut self, generics: &mut Generics) -> Self {
811 let mut visitor = self.clone();
812 for gp in generics.params.iter_mut() {
813 if let GenericParam::Type(TypeParam { ident, .. }) = gp {
814 visitor.0.map.remove(&parse_quote!(#ident));
815 }
816 visitor.visit_generic_param_mut(gp);
817 }
818 visitor
819 }
820
821 fn with_signature(&mut self, sig: &mut Signature) -> Self {
822 let mut visitor = self.with_generics(&mut sig.generics);
823 for input in sig.inputs.iter_mut() {
824 visitor.visit_fn_arg_mut(input);
825 }
826 visitor.visit_return_type_mut(&mut sig.output);
827 visitor
828 }
829}
830
831impl<F: FnMut(usize) -> Path + Clone> VisitMut for Visitor<F> {
832 fn visit_type_mut(&mut self, i: &mut Type) {
833 *i = self.0.expand(i.clone(), &self.1, &mut self.2);
834 }
835 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
836 for attr in i.attrs.iter_mut() {
837 self.visit_attribute_mut(attr);
838 }
839 let mut visitor = self.with_generics(&mut i.generics);
840 visitor.visit_fields_mut(&mut i.fields);
841 }
842 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
843 for attr in i.attrs.iter_mut() {
844 self.visit_attribute_mut(attr);
845 }
846 let mut visitor = self.with_generics(&mut i.generics);
847 for variant in i.variants.iter_mut() {
848 visitor.visit_variant_mut(variant);
849 }
850 }
851 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
852 for attr in i.attrs.iter_mut() {
853 self.visit_attribute_mut(attr);
854 }
855 let mut visitor = self.with_generics(&mut i.generics);
856 for supertrait in i.supertraits.iter_mut() {
857 visitor.visit_type_param_bound_mut(supertrait);
858 }
859 for item in i.items.iter_mut() {
860 visitor.visit_trait_item_mut(item);
861 }
862 }
863 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
864 for attr in i.attrs.iter_mut() {
865 self.visit_attribute_mut(attr);
866 }
867 let mut visitor = self.with_generics(&mut i.generics);
868 visitor.visit_fields_named_mut(&mut i.fields);
869 }
870 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
871 for attr in i.attrs.iter_mut() {
872 self.visit_attribute_mut(attr);
873 }
874 let mut visitor = self.with_generics(&mut i.generics);
875 visitor.visit_type_mut(&mut i.ty);
876 }
877 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
878 for attr in i.attrs.iter_mut() {
879 self.visit_attribute_mut(attr);
880 }
881 let mut visitor = self.with_signature(&mut i.sig);
882 visitor.visit_block_mut(i.block.as_mut());
883 }
884 fn visit_trait_item_fn_mut(&mut self, i: &mut TraitItemFn) {
885 for attr in i.attrs.iter_mut() {
886 self.visit_attribute_mut(attr);
887 }
888 let mut visitor = self.with_signature(&mut i.sig);
889 if let Some(block) = &mut i.default {
890 visitor.visit_block_mut(block);
891 }
892 }
893 fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
894 for attr in i.attrs.iter_mut() {
895 self.visit_attribute_mut(attr);
896 }
897 let mut visitor = self.with_generics(&mut i.generics);
898 for bound in i.bounds.iter_mut() {
899 visitor.visit_type_param_bound_mut(bound);
900 }
901 if let Some((_, ty)) = &mut i.default {
902 visitor.visit_type_mut(ty);
903 }
904 }
905 fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
906 for attr in i.attrs.iter_mut() {
907 self.visit_attribute_mut(attr);
908 }
909 let mut visitor = self.with_generics(&mut i.generics);
910 visitor.visit_type_mut(&mut i.ty);
911 if let Some((_, expr)) = &mut i.default {
912 visitor.visit_expr_mut(expr);
913 }
914 }
915 fn visit_block_mut(&mut self, i: &mut Block) {
916 let mut visitor = self.clone();
917 for stmt in &i.stmts {
918 match stmt {
919 Stmt::Item(Item::Struct(ItemStruct { ident, .. }))
920 | Stmt::Item(Item::Enum(ItemEnum { ident, .. }))
921 | Stmt::Item(Item::Union(ItemUnion { ident, .. }))
922 | Stmt::Item(Item::Trait(ItemTrait { ident, .. }))
923 | Stmt::Item(Item::Type(ItemType { ident, .. })) => {
924 visitor.0.map.remove(&parse_quote!(#ident));
925 }
926 _ => (),
927 }
928 }
929 for stmt in i.stmts.iter_mut() {
930 visitor.visit_stmt_mut(stmt);
931 }
932 }
933}
934
935impl Parse for Referrer {
936 fn parse(input: parse::ParseStream) -> Result<Self> {
937 let mut map = HashMap::new();
938 let map_content: syn::parse::ParseBuffer<'_>;
939 parenthesized!(map_content in input);
940 while !map_content.is_empty() {
941 let key: Type = map_content.parse()?;
942 map_content.parse::<Token![:]>()?;
943 let value: LitInt = map_content.parse()?;
944 map.insert(key, value.base10_parse()?);
945 if map_content.is_empty() {
946 break;
947 }
948 map_content.parse::<Token![,]>()?;
949 }
950 Ok(Self { map })
951 }
952}
953
954impl ToTokens for Referrer {
955 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
956 tokens.extend(quote! {
957 (
958 #(for (key, val) in &self.map), {
959 #key: #val
960 }
961 )
962 })
963 }
964}