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();
638 self.reduce_obvious_nodes();
639 }
641
642 fn reduce_obvious_nodes(&mut self) {
643 let mut must_intern_nodes: Vec<_> = self.must_intern_nodes.iter().cloned().collect();
644 let mut root_nodes: Vec<_> = self.root_nodes.iter().cloned().collect();
645 let nodes: Vec<_> = self
646 .graph
647 .node_indices()
648 .filter_map(|n| {
649 let mut it = self.graph.edges(n.clone());
650 if let Some(edge) = it.next() {
651 if let None = it.next() {
652 return Some((edge.source(), edge.target(), edge.id()));
653 }
654 }
655 None
656 })
657 .collect();
658 let mut removing_nodes = HashSet::new();
659 for (node1, node2, edge) in nodes {
660 self.graph.remove_edge(edge);
661 for (edge_in_source, edge_in) in self
662 .graph
663 .edges_directed(node1, petgraph::Direction::Incoming)
664 .map(|er| (er.source(), er.id()))
665 .collect::<Vec<_>>()
666 {
667 self.graph.update_edge(edge_in_source, node2, ());
668 self.graph.remove_edge(edge_in);
669 }
670 must_intern_nodes.iter_mut().for_each(|n| {
671 if n == &node1 {
672 *n = node2.clone()
673 }
674 });
675 root_nodes.iter_mut().for_each(|n| {
676 if n == &node1 {
677 *n = node2.clone()
678 }
679 });
680 removing_nodes.insert(node1);
681 }
682 let mut new_graph = Graph::new();
683 let mut node_map = HashMap::new();
684 for node in self.graph.node_indices() {
685 if !removing_nodes.contains(&node) {
686 let new_node = new_graph.add_node(self.graph[node].clone());
687 node_map.insert(node, new_node);
688 }
689 }
690 for edge in self.graph.edge_indices() {
691 let (n1, n2) = self.graph.edge_endpoints(edge).unwrap();
692 if let (Some(nn1), Some(nn2)) = (node_map.get(&n1), node_map.get(&n2)) {
693 new_graph.add_edge(*nn1, *nn2, ());
694 }
695 }
696 self.root_nodes = root_nodes
697 .iter()
698 .filter_map(|n| node_map.get(n).cloned())
699 .collect();
700 self.must_intern_nodes = must_intern_nodes
701 .iter()
702 .filter_map(|n| node_map.get(n).cloned())
703 .collect();
704 let _ = std::mem::replace(&mut self.graph, new_graph);
705 }
706
707 fn reduce_unreachable_nodes(&mut self) {
708 let reachable_forward = get_reachable_nodes(&self.graph, self.root_nodes.iter().cloned());
709 self.graph.reverse();
710 let reachable_backward =
711 get_reachable_nodes(&self.graph, self.must_intern_nodes.iter().cloned());
712 self.graph.reverse();
713 let reachable = reachable_forward
714 .intersection(&reachable_backward)
715 .cloned()
716 .collect::<HashSet<_>>();
717 let mut new_graph = Graph::new();
725 let mut node_map = HashMap::new();
726 for node in self.graph.node_indices() {
727 if reachable.contains(&node) {
728 let new_node = new_graph.add_node(self.graph[node].clone());
729 node_map.insert(node, new_node);
730 }
731 }
732 for edge in self.graph.edge_indices() {
733 let (n1, n2) = self.graph.edge_endpoints(edge).unwrap();
734 if let (Some(nn1), Some(nn2)) = (node_map.get(&n1), node_map.get(&n2)) {
735 new_graph.add_edge(*nn1, *nn2, ());
736 }
737 }
738 self.root_nodes = self
739 .root_nodes
740 .iter()
741 .filter_map(|n| node_map.get(n).cloned())
742 .collect();
743 self.must_intern_nodes = self
744 .must_intern_nodes
745 .iter()
746 .filter_map(|n| node_map.get(n).cloned())
747 .collect();
748 let _ = std::mem::replace(&mut self.graph, new_graph);
749 }
750}
751
752fn get_reachable_nodes<N, E>(
753 graph: &Graph<N, E>,
754 roots: impl IntoIterator<Item = NodeIndex<DefaultIx>>,
755) -> HashSet<NodeIndex<DefaultIx>> {
756 let mut ret: HashSet<_> = roots.into_iter().collect();
757 let mut frontier = ret.clone();
758 loop {
759 let mut buf: HashSet<_> = frontier
760 .iter()
761 .map(|node| graph.neighbors(node.clone()))
762 .flatten()
763 .collect();
764 let mut count = 0;
765 for node in &buf {
766 if ret.insert(node.clone()) {
767 count += 1;
768 }
769 }
770 if count == 0 {
771 break;
772 }
773 std::mem::swap(&mut frontier, &mut buf);
774 }
775 ret
776}
777
778#[derive(Clone, PartialEq, Eq, Debug)]
779pub struct Referrer {
780 map: HashMap<Type, usize>,
781}
782
783impl Referrer {
784 pub fn is_empty(&self) -> bool {
785 self.map.is_empty()
786 }
787
788 pub fn iter(&self) -> impl Iterator<Item = &Type> {
789 self.map.keys()
790 }
791
792 pub fn into_visitor<F: FnMut(usize) -> Path + Clone>(
793 self,
794 leaker_ty: Type,
795 repeater_path_fn: F,
796 ) -> Visitor<F> {
797 Visitor(self, leaker_ty, repeater_path_fn)
798 }
799
800 pub fn expand(
801 &self,
802 ty: Type,
803 leaker_ty: &Type,
804 repeater_path_fn: impl FnMut(usize) -> Path,
805 ) -> Type {
806 use syn::fold::Fold;
807
808 struct Folder<'a, F>(&'a Referrer, &'a Type, F);
809 impl<'a, F: FnMut(usize) -> Path> Fold for Folder<'a, F> {
810 fn fold_type(&mut self, ty: Type) -> Type {
811 if let Some(idx) = self.0.map.get(&ty) {
812 parse2(quote! {
813 <#{&self.1} as #{&self.2(*idx)}>::Type
814 })
815 .unwrap()
816 } else {
817 syn::fold::fold_type(self, ty)
818 }
819 }
820 }
821 let mut folder = Folder(self, leaker_ty, repeater_path_fn);
822 folder.fold_type(ty)
823 }
824}
825
826#[derive(Clone, Debug)]
827pub struct Visitor<F>(Referrer, Type, F);
828
829impl<F: FnMut(usize) -> Path + Clone> Visitor<F> {
830 fn with_generics(&mut self, generics: &mut Generics) -> Self {
831 let mut visitor = self.clone();
832 for gp in generics.params.iter_mut() {
833 if let GenericParam::Type(TypeParam { ident, .. }) = gp {
834 visitor.0.map.remove(&parse_quote!(#ident));
835 }
836 visitor.visit_generic_param_mut(gp);
837 }
838 visitor
839 }
840
841 fn with_signature(&mut self, sig: &mut Signature) -> Self {
842 let mut visitor = self.with_generics(&mut sig.generics);
843 for input in sig.inputs.iter_mut() {
844 visitor.visit_fn_arg_mut(input);
845 }
846 visitor.visit_return_type_mut(&mut sig.output);
847 visitor
848 }
849}
850
851impl<F: FnMut(usize) -> Path + Clone> VisitMut for Visitor<F> {
852 fn visit_type_mut(&mut self, i: &mut Type) {
853 *i = self.0.expand(i.clone(), &self.1, &mut self.2);
854 }
855 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
856 for attr in i.attrs.iter_mut() {
857 self.visit_attribute_mut(attr);
858 }
859 let mut visitor = self.with_generics(&mut i.generics);
860 visitor.visit_fields_mut(&mut i.fields);
861 }
862 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
863 for attr in i.attrs.iter_mut() {
864 self.visit_attribute_mut(attr);
865 }
866 let mut visitor = self.with_generics(&mut i.generics);
867 for variant in i.variants.iter_mut() {
868 visitor.visit_variant_mut(variant);
869 }
870 }
871 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
872 for attr in i.attrs.iter_mut() {
873 self.visit_attribute_mut(attr);
874 }
875 let mut visitor = self.with_generics(&mut i.generics);
876 for supertrait in i.supertraits.iter_mut() {
877 visitor.visit_type_param_bound_mut(supertrait);
878 }
879 for item in i.items.iter_mut() {
880 visitor.visit_trait_item_mut(item);
881 }
882 }
883 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
884 for attr in i.attrs.iter_mut() {
885 self.visit_attribute_mut(attr);
886 }
887 let mut visitor = self.with_generics(&mut i.generics);
888 visitor.visit_fields_named_mut(&mut i.fields);
889 }
890 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
891 for attr in i.attrs.iter_mut() {
892 self.visit_attribute_mut(attr);
893 }
894 let mut visitor = self.with_generics(&mut i.generics);
895 visitor.visit_type_mut(&mut i.ty);
896 }
897 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
898 for attr in i.attrs.iter_mut() {
899 self.visit_attribute_mut(attr);
900 }
901 let mut visitor = self.with_signature(&mut i.sig);
902 visitor.visit_block_mut(i.block.as_mut());
903 }
904 fn visit_trait_item_fn_mut(&mut self, i: &mut TraitItemFn) {
905 for attr in i.attrs.iter_mut() {
906 self.visit_attribute_mut(attr);
907 }
908 let mut visitor = self.with_signature(&mut i.sig);
909 if let Some(block) = &mut i.default {
910 visitor.visit_block_mut(block);
911 }
912 }
913 fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
914 for attr in i.attrs.iter_mut() {
915 self.visit_attribute_mut(attr);
916 }
917 let mut visitor = self.with_generics(&mut i.generics);
918 for bound in i.bounds.iter_mut() {
919 visitor.visit_type_param_bound_mut(bound);
920 }
921 if let Some((_, ty)) = &mut i.default {
922 visitor.visit_type_mut(ty);
923 }
924 }
925 fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
926 for attr in i.attrs.iter_mut() {
927 self.visit_attribute_mut(attr);
928 }
929 let mut visitor = self.with_generics(&mut i.generics);
930 visitor.visit_type_mut(&mut i.ty);
931 if let Some((_, expr)) = &mut i.default {
932 visitor.visit_expr_mut(expr);
933 }
934 }
935 fn visit_block_mut(&mut self, i: &mut Block) {
936 let mut visitor = self.clone();
937 for stmt in &i.stmts {
938 match stmt {
939 Stmt::Item(Item::Struct(ItemStruct { ident, .. }))
940 | Stmt::Item(Item::Enum(ItemEnum { ident, .. }))
941 | Stmt::Item(Item::Union(ItemUnion { ident, .. }))
942 | Stmt::Item(Item::Trait(ItemTrait { ident, .. }))
943 | Stmt::Item(Item::Type(ItemType { ident, .. })) => {
944 visitor.0.map.remove(&parse_quote!(#ident));
945 }
946 _ => (),
947 }
948 }
949 for stmt in i.stmts.iter_mut() {
950 visitor.visit_stmt_mut(stmt);
951 }
952 }
953}
954
955impl Parse for Referrer {
956 fn parse(input: parse::ParseStream) -> Result<Self> {
957 let mut map = HashMap::new();
958 let map_content: syn::parse::ParseBuffer<'_>;
959 parenthesized!(map_content in input);
960 while !map_content.is_empty() {
961 let key: Type = map_content.parse()?;
962 map_content.parse::<Token![:]>()?;
963 let value: LitInt = map_content.parse()?;
964 map.insert(key, value.base10_parse()?);
965 if map_content.is_empty() {
966 break;
967 }
968 map_content.parse::<Token![,]>()?;
969 }
970 Ok(Self { map })
971 }
972}
973
974impl ToTokens for Referrer {
975 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
976 tokens.extend(quote! {
977 (
978 #(for (key, val) in &self.map), {
979 #key: #val
980 }
981 )
982 })
983 }
984}