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(_)
416 | Type::Infer(_)
417 | Type::Macro(_)
418 | Type::Verbatim(_) => {
419 self.impossible = Some(i.span());
420 }
421 _ => (),
422 }
423 let mut visitor = self.clone();
424 visitor.must = None;
425 syn::visit::visit_type(&mut visitor, i);
426 if visitor.impossible.is_some() {
427 self.impossible = visitor.impossible;
428 }
429 match (self.must.clone(), visitor.must.clone()) {
430 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
431 self.must = Some((v_l + 1, v_m))
432 }
433 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
434 _ => (),
435 }
436 }
437 fn visit_qself(&mut self, i: &QSelf) {
438 if i.as_token.is_none() {
439 self.impossible = Some(i.span());
440 }
441 syn::visit::visit_qself(self, i)
442 }
443 fn visit_lifetime(&mut self, i: &Lifetime) {
444 if i.to_string() != "'static"
445 && !self.generic_lifetimes.iter().any(|lt| lt == i)
446 {
447 self.must = Some((-1, i.span()));
448 }
449 syn::visit::visit_lifetime(self, i)
450 }
451 fn visit_expr(&mut self, i: &Expr) {
452 match i {
453 Expr::Closure(_)
454 | Expr::Assign(_)
455 | Expr::Verbatim(_)
456 | Expr::Macro(_)
457 | Expr::Infer(_) => {
458 self.impossible = Some(i.span());
459 }
460 _ => (),
461 }
462 syn::visit::visit_expr(self, i)
463 }
464 fn visit_path(&mut self, i: &Path) {
465 if matches!(i.segments.iter().next(), Some(PathSegment { ident, arguments }) if ident == "Self" && arguments.is_none())
466 {
467 } else {
469 match (i.leading_colon, i.get_ident()) {
470 (None, Some(ident))
472 if self.generic_idents.contains(&ident) || ident == "Self" => {}
473 (None, _) => {
475 self.must = Some((-1, i.span()));
476 }
477 (Some(_), _) => (),
479 }
480 }
481
482 syn::visit::visit_path(self, i)
483 }
484 }
485 };
486 let mut visitor = Visitor {
487 generic_lifetimes: generics
488 .params
489 .iter()
490 .filter_map(|gp| {
491 if let GenericParam::Lifetime(lt) = gp {
492 Some(lt.lifetime.clone())
493 } else {
494 None
495 }
496 })
497 .collect(),
498 generic_idents: generics
499 .params
500 .iter()
501 .filter_map(|gp| match gp {
502 GenericParam::Type(TypeParam { ident, .. })
503 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
504 _ => None,
505 })
506 .collect(),
507 impossible: None,
508 must: None,
509 };
510 visitor.visit_type(ty);
511 match (visitor.must, visitor.impossible) {
512 (None, None) => Ok(CheckResult::Neutral),
513 (Some((0, span)), None) => Ok(CheckResult::MustIntern(span)),
514 (Some((_, span)), None) => Ok(CheckResult::MustInternOrInherit(span)),
515 (None, Some(span)) => Ok(CheckResult::MustNotIntern(span)),
516 (Some((_, span0)), Some(span1)) => Err((span0, span1)),
517 }
518 }
519
520 pub fn finish(
522 self,
523 mut repeater_path_fn: impl FnMut(usize) -> Path,
524 ) -> (Vec<ItemImpl>, Referrer) {
525 let (impl_generics, _, where_clause) = self.generics.split_for_impl();
526 let id_map: HashMap<_, _> = self
527 .root_nodes
528 .iter()
529 .enumerate()
530 .map(|(n, idx)| {
531 (
532 self.graph.node_weight(idx.clone()).expect("hello3").clone(),
533 n,
534 )
535 })
536 .collect();
537 let path_args = PathArguments::AngleBracketed(AngleBracketedGenericArguments {
538 colon2_token: None,
539 lt_token: Token),
540 args: self
541 .generics
542 .params
543 .iter()
544 .map(|param| match param {
545 GenericParam::Lifetime(lifetime_param) => {
546 GenericArgument::Lifetime(lifetime_param.lifetime.clone())
547 }
548 GenericParam::Type(TypeParam { ident, .. }) => {
549 GenericArgument::Type(parse_quote!(#ident))
550 }
551 GenericParam::Const(ConstParam { ident, .. }) => {
552 GenericArgument::Const(parse_quote!(#ident))
553 }
554 })
555 .collect(),
556 gt_token: Token),
557 });
558 (
559 id_map
560 .iter()
561 .map(|(ty, n)| {
562 parse2(quote! {
563 impl #impl_generics #{repeater_path_fn(*n)} for #{(*self.implementor_type_fn)(path_args.clone())} #where_clause {
564 type Type = #ty;
565 }
566 }).expect("hello4")
567 })
568 .collect(),
569 Referrer { map: id_map },
570 )
571 }
572
573 #[cfg_attr(doc, aquamarine::aquamarine)]
574 pub fn reduce_roots(&mut self) {
643 self.reduce_unreachable_nodes();
644 self.reduce_obvious_nodes();
645 }
647
648 fn reduce_obvious_nodes(&mut self) {
649 let mut must_intern_nodes: Vec<_> = self.must_intern_nodes.iter().cloned().collect();
650 let mut root_nodes: Vec<_> = self.root_nodes.iter().cloned().collect();
651 let nodes: Vec<_> = self
652 .graph
653 .node_indices()
654 .filter_map(|n| {
655 let mut it = self.graph.edges(n.clone());
656 if let Some(edge) = it.next() {
657 if let None = it.next() {
658 return Some((edge.source(), edge.target(), edge.id()));
659 }
660 }
661 None
662 })
663 .collect();
664 for (node1, node2, edge) in nodes {
665 self.graph.remove_edge(edge);
666 for (edge_in_source, edge_in) in self
667 .graph
668 .edges_directed(node1, petgraph::Direction::Incoming)
669 .map(|er| (er.source(), er.id()))
670 .collect::<Vec<_>>()
671 {
672 self.graph.update_edge(edge_in_source, node2, ());
673 self.graph.remove_edge(edge_in);
674 }
675 must_intern_nodes.iter_mut().for_each(|n| {
676 if n == &node1 {
677 *n = node2.clone()
678 }
679 });
680 root_nodes.iter_mut().for_each(|n| {
681 if n == &node1 {
682 *n = node2.clone()
683 }
684 });
685 self.graph.remove_node(node1);
686 }
687 self.must_intern_nodes = must_intern_nodes.into_iter().collect();
688 self.root_nodes = root_nodes.into_iter().collect();
689 }
690
691 fn reduce_unreachable_nodes(&mut self) {
692 let reachable_forward = get_reachable_nodes(&self.graph, self.root_nodes.iter().cloned());
693 self.graph.reverse();
694 let reachable_backward =
695 get_reachable_nodes(&self.graph, self.must_intern_nodes.iter().cloned());
696 self.graph.reverse();
697 let reachable = reachable_forward
698 .intersection(&reachable_backward)
699 .cloned()
700 .collect::<HashSet<_>>();
701 let mut new_graph = Graph::new();
709 let mut node_map = HashMap::new();
710 for node in self.graph.node_indices() {
711 if reachable.contains(&node) {
712 let new_node = new_graph.add_node(self.graph[node].clone());
713 node_map.insert(node, new_node);
714 }
715 }
716 for edge in self.graph.edge_indices() {
717 let (n1, n2) = self.graph.edge_endpoints(edge).unwrap();
718 if let (Some(nn1), Some(nn2)) = (node_map.get(&n1), node_map.get(&n2)) {
719 new_graph.add_edge(*nn1, *nn2, ());
720 }
721 }
722 self.root_nodes = self
723 .root_nodes
724 .iter()
725 .filter_map(|n| node_map.get(n).cloned())
726 .collect();
727 self.must_intern_nodes = self
728 .must_intern_nodes
729 .iter()
730 .filter_map(|n| node_map.get(n).cloned())
731 .collect();
732 let _ = std::mem::replace(&mut self.graph, new_graph);
733 }
734}
735
736fn get_reachable_nodes<N, E>(
737 graph: &Graph<N, E>,
738 roots: impl IntoIterator<Item = NodeIndex<DefaultIx>>,
739) -> HashSet<NodeIndex<DefaultIx>> {
740 let mut ret: HashSet<_> = roots.into_iter().collect();
741 let mut frontier = ret.clone();
742 loop {
743 let mut buf: HashSet<_> = frontier
744 .iter()
745 .map(|node| graph.neighbors(node.clone()))
746 .flatten()
747 .collect();
748 let mut count = 0;
749 for node in &buf {
750 if ret.insert(node.clone()) {
751 count += 1;
752 }
753 }
754 if count == 0 {
755 break;
756 }
757 std::mem::swap(&mut frontier, &mut buf);
758 }
759 ret
760}
761
762#[derive(Clone, PartialEq, Eq, Debug)]
763pub struct Referrer {
764 map: HashMap<Type, usize>,
765}
766
767impl Referrer {
768 pub fn is_empty(&self) -> bool {
769 self.map.is_empty()
770 }
771
772 pub fn iter(&self) -> impl Iterator<Item = &Type> {
773 self.map.keys()
774 }
775
776 pub fn into_visitor<F: FnMut(usize) -> Path + Clone>(
777 self,
778 leaker_ty: Type,
779 repeater_path_fn: F,
780 ) -> Visitor<F> {
781 Visitor(self, leaker_ty, repeater_path_fn)
782 }
783
784 pub fn expand(
785 &self,
786 ty: Type,
787 leaker_ty: &Type,
788 repeater_path_fn: impl FnMut(usize) -> Path,
789 ) -> Type {
790 use syn::fold::Fold;
791
792 struct Folder<'a, F>(&'a Referrer, &'a Type, F);
793 impl<'a, F: FnMut(usize) -> Path> Fold for Folder<'a, F> {
794 fn fold_type(&mut self, ty: Type) -> Type {
795 if let Some(idx) = self.0.map.get(&ty) {
796 parse2(quote! {
797 <#{&self.1} as #{&self.2(*idx)}>::Type
798 })
799 .unwrap()
800 } else {
801 syn::fold::fold_type(self, ty)
802 }
803 }
804 }
805 let mut folder = Folder(self, leaker_ty, repeater_path_fn);
806 folder.fold_type(ty)
807 }
808}
809
810#[derive(Clone, Debug)]
811pub struct Visitor<F>(Referrer, Type, F);
812
813impl<F: FnMut(usize) -> Path + Clone> Visitor<F> {
814 fn with_generics(&mut self, generics: &mut Generics) -> Self {
815 let mut visitor = self.clone();
816 for gp in generics.params.iter_mut() {
817 if let GenericParam::Type(TypeParam { ident, .. }) = gp {
818 visitor.0.map.remove(&parse_quote!(#ident));
819 }
820 visitor.visit_generic_param_mut(gp);
821 }
822 visitor
823 }
824
825 fn with_signature(&mut self, sig: &mut Signature) -> Self {
826 let mut visitor = self.with_generics(&mut sig.generics);
827 for input in sig.inputs.iter_mut() {
828 visitor.visit_fn_arg_mut(input);
829 }
830 visitor.visit_return_type_mut(&mut sig.output);
831 visitor
832 }
833}
834
835impl<F: FnMut(usize) -> Path + Clone> VisitMut for Visitor<F> {
836 fn visit_type_mut(&mut self, i: &mut Type) {
837 *i = self.0.expand(i.clone(), &self.1, &mut self.2);
838 }
839 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
840 for attr in i.attrs.iter_mut() {
841 self.visit_attribute_mut(attr);
842 }
843 let mut visitor = self.with_generics(&mut i.generics);
844 visitor.visit_fields_mut(&mut i.fields);
845 }
846 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
847 for attr in i.attrs.iter_mut() {
848 self.visit_attribute_mut(attr);
849 }
850 let mut visitor = self.with_generics(&mut i.generics);
851 for variant in i.variants.iter_mut() {
852 visitor.visit_variant_mut(variant);
853 }
854 }
855 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
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 for supertrait in i.supertraits.iter_mut() {
861 visitor.visit_type_param_bound_mut(supertrait);
862 }
863 for item in i.items.iter_mut() {
864 visitor.visit_trait_item_mut(item);
865 }
866 }
867 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
868 for attr in i.attrs.iter_mut() {
869 self.visit_attribute_mut(attr);
870 }
871 let mut visitor = self.with_generics(&mut i.generics);
872 visitor.visit_fields_named_mut(&mut i.fields);
873 }
874 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
875 for attr in i.attrs.iter_mut() {
876 self.visit_attribute_mut(attr);
877 }
878 let mut visitor = self.with_generics(&mut i.generics);
879 visitor.visit_type_mut(&mut i.ty);
880 }
881 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
882 for attr in i.attrs.iter_mut() {
883 self.visit_attribute_mut(attr);
884 }
885 let mut visitor = self.with_signature(&mut i.sig);
886 visitor.visit_block_mut(i.block.as_mut());
887 }
888 fn visit_trait_item_fn_mut(&mut self, i: &mut TraitItemFn) {
889 for attr in i.attrs.iter_mut() {
890 self.visit_attribute_mut(attr);
891 }
892 let mut visitor = self.with_signature(&mut i.sig);
893 if let Some(block) = &mut i.default {
894 visitor.visit_block_mut(block);
895 }
896 }
897 fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
898 for attr in i.attrs.iter_mut() {
899 self.visit_attribute_mut(attr);
900 }
901 let mut visitor = self.with_generics(&mut i.generics);
902 for bound in i.bounds.iter_mut() {
903 visitor.visit_type_param_bound_mut(bound);
904 }
905 if let Some((_, ty)) = &mut i.default {
906 visitor.visit_type_mut(ty);
907 }
908 }
909 fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
910 for attr in i.attrs.iter_mut() {
911 self.visit_attribute_mut(attr);
912 }
913 let mut visitor = self.with_generics(&mut i.generics);
914 visitor.visit_type_mut(&mut i.ty);
915 if let Some((_, expr)) = &mut i.default {
916 visitor.visit_expr_mut(expr);
917 }
918 }
919 fn visit_block_mut(&mut self, i: &mut Block) {
920 let mut visitor = self.clone();
921 for stmt in &i.stmts {
922 match stmt {
923 Stmt::Item(Item::Struct(ItemStruct { ident, .. }))
924 | Stmt::Item(Item::Enum(ItemEnum { ident, .. }))
925 | Stmt::Item(Item::Union(ItemUnion { ident, .. }))
926 | Stmt::Item(Item::Trait(ItemTrait { ident, .. }))
927 | Stmt::Item(Item::Type(ItemType { ident, .. })) => {
928 visitor.0.map.remove(&parse_quote!(#ident));
929 }
930 _ => (),
931 }
932 }
933 for stmt in i.stmts.iter_mut() {
934 visitor.visit_stmt_mut(stmt);
935 }
936 }
937}
938
939impl Parse for Referrer {
940 fn parse(input: parse::ParseStream) -> Result<Self> {
941 let mut map = HashMap::new();
942 let map_content: syn::parse::ParseBuffer<'_>;
943 parenthesized!(map_content in input);
944 while !map_content.is_empty() {
945 let key: Type = map_content.parse()?;
946 map_content.parse::<Token![:]>()?;
947 let value: LitInt = map_content.parse()?;
948 map.insert(key, value.base10_parse()?);
949 if map_content.is_empty() {
950 break;
951 }
952 map_content.parse::<Token![,]>()?;
953 }
954 Ok(Self { map })
955 }
956}
957
958impl ToTokens for Referrer {
959 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
960 tokens.extend(quote! {
961 (
962 #(for (key, val) in &self.map), {
963 #key: #val
964 }
965 )
966 })
967 }
968}