1#![doc = include_str!("./README.md")]
2
3use gotgraph::graph::{Graph as GotGraph, GraphUpdate};
4use gotgraph::prelude::VecGraph;
5use proc_macro2::Span;
6use std::cell::RefCell;
7use std::collections::{HashMap, HashSet};
8use std::rc::Rc;
9use syn::parse::Parse;
10use syn::punctuated::Punctuated;
11use syn::spanned::Spanned;
12use syn::visit::Visit;
13use syn::visit_mut::VisitMut;
14use syn::*;
15use template_quote::{quote, ToTokens};
16
17pub use syn;
18
19pub struct Leaker {
21 generics: Generics,
22 graph: VecGraph<Type, ()>,
23 pub self_ty_can_be_interned: bool,
24 reachable_types: HashSet<Type>,
25 pending_operations: Option<Vec<GraphOperation>>,
26}
27
28#[derive(Debug, Clone)]
30pub struct NotInternableError(pub Span);
31
32impl std::fmt::Display for NotInternableError {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.write_str("Not internable")
35 }
36}
37
38impl std::error::Error for NotInternableError {}
39
40pub fn encode_generics_args_to_ty<'a>(iter: impl IntoIterator<Item = &'a GenericArgument>) -> Type {
42 Type::Tuple(TypeTuple {
43 paren_token: Default::default(),
44 elems: iter
45 .into_iter()
46 .map(|param| -> Type {
47 match param {
48 GenericArgument::Lifetime(lifetime) => {
49 parse_quote!(& #lifetime ())
50 }
51 GenericArgument::Const(expr) => {
52 parse_quote!([(); #expr as usize])
53 }
54 GenericArgument::Type(ty) => ty.clone(),
55 _ => panic!(),
56 }
57 })
58 .collect(),
59 })
60}
61
62pub fn encode_generics_params_to_ty<'a>(iter: impl IntoIterator<Item = &'a GenericParam>) -> Type {
64 Type::Tuple(TypeTuple {
65 paren_token: Default::default(),
66 elems: iter
67 .into_iter()
68 .map(|param| -> Type {
69 match param {
70 GenericParam::Lifetime(LifetimeParam { lifetime, .. }) => {
71 parse_quote!(& #lifetime ())
72 }
73 GenericParam::Const(ConstParam { ident, .. }) => {
74 parse_quote!([(); #ident as usize])
75 }
76 GenericParam::Type(TypeParam { ident, .. }) => parse_quote!(#ident),
77 }
78 })
79 .collect(),
80 })
81}
82
83#[derive(Clone, Debug)]
85pub enum CheckResult {
86 MustIntern(Span),
88 MustInternOrInherit(Span),
91 MustNotIntern(Span),
94 Neutral,
96}
97
98#[derive(Debug, Clone)]
99struct GraphOperation {
100 node_type: Type,
101 parent: Option<Type>,
102 is_root: bool,
103 is_must_intern: bool,
104}
105
106struct AnalyzeVisitor<'a> {
107 leaker: &'a mut Leaker,
108 generics: Generics,
109 parent: Option<Type>,
110 error: Option<Span>,
111 operations: Vec<GraphOperation>,
112}
113
114impl<'a, 'ast> Visit<'ast> for AnalyzeVisitor<'a> {
115 fn visit_trait_item_fn(&mut self, i: &TraitItemFn) {
116 let mut visitor = AnalyzeVisitor {
117 leaker: &mut self.leaker,
118 generics: self.generics.clone(),
119 parent: self.parent.clone(),
120 error: self.error.clone(),
121 operations: Vec::new(),
122 };
123 for g in &i.sig.generics.params {
124 visitor.generics.params.push(g.clone());
125 }
126 let mut i = i.clone();
127 i.default = None;
128 i.semi_token = Some(Default::default());
129 syn::visit::visit_trait_item_fn(&mut visitor, &mut i);
130 self.error = visitor.error;
131 self.operations.extend(visitor.operations);
132 }
133
134 fn visit_receiver(&mut self, i: &Receiver) {
135 for attr in &i.attrs {
136 self.visit_attribute(attr);
137 }
138 if let Some((_, Some(lt))) = &i.reference {
139 self.visit_lifetime(lt);
140 }
141 if i.colon_token.is_some() {
142 self.visit_type(&i.ty);
143 }
144 }
145
146 fn visit_trait_item_type(&mut self, i: &TraitItemType) {
147 let mut visitor = AnalyzeVisitor {
148 leaker: &mut self.leaker,
149 generics: self.generics.clone(),
150 parent: self.parent.clone(),
151 error: self.error.clone(),
152 operations: Vec::new(),
153 };
154 for g in &i.generics.params {
155 visitor.generics.params.push(g.clone());
156 }
157 syn::visit::visit_trait_item_type(&mut visitor, i);
158 self.error = visitor.error;
159 self.operations.extend(visitor.operations);
160 }
161
162 fn visit_type(&mut self, i: &Type) {
163 match self.leaker.check(i) {
164 Err((_, s)) => {
165 self.error = Some(s);
167 }
168 Ok(CheckResult::MustNotIntern(_)) => (),
169 o => {
170 let is_must_intern = matches!(o, Ok(CheckResult::MustIntern(_)));
172 let is_root = self.parent.is_none();
173
174 self.operations.push(GraphOperation {
175 node_type: i.clone(),
176 parent: self.parent.clone(),
177 is_root,
178 is_must_intern,
179 });
180
181 if !is_must_intern {
182 let parent = self.parent.clone();
184 self.parent = Some(i.clone());
185 syn::visit::visit_type(self, i);
186 self.parent = parent;
187 }
188 }
189 }
190 }
191
192 fn visit_trait_bound(&mut self, i: &TraitBound) {
193 if i.path.leading_colon.is_none() {
194 self.error = Some(i.span());
196 } else {
197 syn::visit::visit_trait_bound(self, i)
198 }
199 }
200
201 fn visit_expr_path(&mut self, i: &ExprPath) {
202 if i.path.leading_colon.is_none() {
203 self.error = Some(i.span());
205 } else {
206 syn::visit::visit_expr_path(self, i)
207 }
208 }
209}
210
211impl Default for Leaker {
212 fn default() -> Self {
213 Self::with_generics(Generics::default())
214 }
215}
216
217impl Leaker {
218 pub fn from_struct(input: &ItemStruct) -> std::result::Result<Self, NotInternableError> {
233 let mut leaker = Self::with_generics(input.generics.clone());
234 leaker.intern_with(|visitor| {
235 visitor.visit_item_struct(input);
236 })?;
237 Ok(leaker)
238 }
239
240 pub fn from_enum(input: &ItemEnum) -> std::result::Result<Self, NotInternableError> {
242 let mut leaker = Self::with_generics(input.generics.clone());
243 leaker.intern_with(|visitor| {
244 visitor.visit_item_enum(input);
245 })?;
246 Ok(leaker)
247 }
248
249 pub fn from_trait(input: &ItemTrait) -> std::result::Result<Self, NotInternableError> {
270 let mut leaker = Self::with_generics(input.generics.clone());
271 leaker.intern_with(|visitor| {
272 visitor.visit_item_trait(input);
273 })?;
274 Ok(leaker)
275 }
276
277 pub fn new() -> Self {
279 Self::default()
280 }
281
282 pub fn with_generics(generics: Generics) -> Self {
287 Self {
288 generics,
289 graph: VecGraph::default(),
290 self_ty_can_be_interned: true,
291 reachable_types: HashSet::new(),
292 pending_operations: None,
293 }
294 }
295
296 fn apply_operations(&mut self, operations: Vec<GraphOperation>) {
298 if operations.is_empty() {
299 return;
300 }
301
302 self.pending_operations = Some(operations);
304 }
305
306 pub fn intern_with<'ast, F>(
308 &mut self,
309 f: F,
310 ) -> std::result::Result<&mut Self, NotInternableError>
311 where
312 F: FnOnce(&mut dyn syn::visit::Visit<'ast>),
313 {
314 let generics = self.generics.clone();
315 let mut visitor = AnalyzeVisitor {
316 leaker: self,
317 parent: None,
318 error: None,
319 generics,
320 operations: Vec::new(),
321 };
322 f(&mut visitor);
323 if let Some(e) = visitor.error {
324 Err(NotInternableError(e))
325 } else {
326 let operations = visitor.operations;
327 self.apply_operations(operations);
328 Ok(self)
329 }
330 }
331
332 pub fn check(&self, ty: &Type) -> std::result::Result<CheckResult, (Span, Span)> {
338 use syn::visit::Visit;
339 #[derive(Clone)]
340 struct Visitor {
341 generic_lifetimes_base: Vec<Lifetime>,
342 generic_idents_base: Vec<Ident>,
343 generic_lifetimes: Vec<Lifetime>,
344 generic_idents: Vec<Ident>,
345 impossible: Option<Span>,
346 must: Option<(isize, Span)>,
347 self_ty_can_be_interned: bool,
348 }
349
350 const _: () = {
351 use syn::visit::Visit;
352 impl<'a> Visit<'a> for Visitor {
353 fn visit_type(&mut self, i: &Type) {
354 match i {
355 Type::BareFn(TypeBareFn {
356 lifetimes,
357 inputs,
358 output,
359 ..
360 }) => {
361 let mut visitor = self.clone();
362 visitor.must = None;
363 visitor.generic_lifetimes.extend(
364 lifetimes
365 .as_ref()
366 .map(|ls| {
367 ls.lifetimes.iter().map(|gp| {
368 if let GenericParam::Lifetime(lt) = gp {
369 lt.lifetime.clone()
370 } else {
371 panic!()
372 }
373 })
374 })
375 .into_iter()
376 .flatten(),
377 );
378 for input in inputs {
379 visitor.visit_type(&input.ty);
380 }
381 if let ReturnType::Type(_, output) = output {
382 visitor.visit_type(output.as_ref());
383 }
384 if self.impossible.is_none() {
385 self.impossible = visitor.impossible;
386 }
387 match (self.must.clone(), visitor.must.clone()) {
388 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
389 self.must = Some((v_l + 1, v_m))
390 }
391 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
392 _ => (),
393 }
394 return;
395 }
396 Type::TraitObject(TypeTraitObject { bounds, .. }) => {
397 for bound in bounds {
398 match bound {
399 TypeParamBound::Trait(TraitBound {
400 lifetimes, path, ..
401 }) => {
402 let mut visitor = self.clone();
403 visitor.must = None;
404 visitor.generic_lifetimes.extend(
405 lifetimes
406 .as_ref()
407 .map(|ls| {
408 ls.lifetimes.iter().map(|gp| {
409 if let GenericParam::Lifetime(lt) = gp {
410 lt.lifetime.clone()
411 } else {
412 panic!()
413 }
414 })
415 })
416 .into_iter()
417 .flatten(),
418 );
419 visitor.visit_path(path);
420 if self.impossible.is_none() {
421 self.impossible = visitor.impossible;
422 }
423 match (self.must.clone(), visitor.must.clone()) {
424 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
425 self.must = Some((v_l + 1, v_m))
426 }
427 (None, Some((v_l, v_m))) => {
428 self.must = Some((v_l + 1, v_m))
429 }
430 _ => (),
431 }
432 return;
433 }
434 TypeParamBound::Verbatim(_) => {
435 self.impossible = Some(bound.span());
436 return;
437 }
438 _ => (),
439 }
440 }
441 }
442 Type::ImplTrait(_) | Type::Macro(_) | Type::Verbatim(_) => {
443 self.impossible = Some(i.span());
444 }
445 Type::Reference(TypeReference { lifetime, .. }) => {
446 if lifetime.is_none() {
447 self.impossible = Some(i.span());
448 }
449 }
450 _ => (),
451 }
452 let mut visitor = self.clone();
453 visitor.must = None;
454 syn::visit::visit_type(&mut visitor, i);
455 if visitor.impossible.is_some() {
456 self.impossible = visitor.impossible;
457 }
458 match (self.must.clone(), visitor.must.clone()) {
459 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
460 self.must = Some((v_l + 1, v_m))
461 }
462 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
463 _ => (),
464 }
465 }
466 fn visit_qself(&mut self, i: &QSelf) {
467 if i.as_token.is_none() {
468 self.impossible = Some(i.span());
469 }
470 syn::visit::visit_qself(self, i)
471 }
472 fn visit_lifetime(&mut self, i: &Lifetime) {
473 match i.to_string().as_str() {
474 "'static" => (),
475 "'_" => self.impossible = Some(i.span()),
476 _ if self.generic_lifetimes_base.iter().any(|lt| lt == i) => {}
477 _ if self.generic_lifetimes.iter().any(|lt| lt == i) => {
478 self.impossible = Some(i.span());
479 }
480 _ => {
481 self.must = Some((-1, i.span()));
482 }
483 }
484 syn::visit::visit_lifetime(self, i)
485 }
486 fn visit_expr(&mut self, i: &Expr) {
487 match i {
488 Expr::Closure(_) | Expr::Assign(_) | Expr::Verbatim(_) | Expr::Macro(_) => {
489 self.impossible = Some(i.span());
490 }
491 _ => (),
492 }
493 syn::visit::visit_expr(self, i)
494 }
495 fn visit_path(&mut self, i: &Path) {
496 if matches!(i.segments.iter().next(), Some(PathSegment { ident, arguments }) if ident == "Self" && arguments.is_none())
497 && i.leading_colon.is_none()
498 {
499 if !self.self_ty_can_be_interned {
500 self.impossible = Some(i.span());
501 }
502 } else {
503 match (i.leading_colon, i.get_ident()) {
504 (None, Some(ident)) if self.generic_idents_base.contains(&ident) => {}
506 (None, Some(ident)) if self.generic_idents.contains(&ident) => {
507 self.impossible = Some(i.span());
508 }
509 (None, _) => {
511 self.must = Some((-1, i.span()));
512 }
513 (Some(_), _) => (),
515 }
516 }
517 syn::visit::visit_path(self, i)
518 }
519 }
520 };
521 let mut visitor = Visitor {
522 generic_lifetimes_base: self
523 .generics
524 .params
525 .iter()
526 .filter_map(|gp| {
527 if let GenericParam::Lifetime(lt) = gp {
528 Some(lt.lifetime.clone())
529 } else {
530 None
531 }
532 })
533 .collect(),
534 generic_idents_base: self
535 .generics
536 .params
537 .iter()
538 .filter_map(|gp| match gp {
539 GenericParam::Type(TypeParam { ident, .. })
540 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
541 _ => None,
542 })
543 .collect(),
544 generic_lifetimes: self
545 .generics
546 .params
547 .iter()
548 .filter_map(|gp| {
549 if let GenericParam::Lifetime(lt) = gp {
550 Some(lt.lifetime.clone())
551 } else {
552 None
553 }
554 })
555 .collect(),
556 generic_idents: self
557 .generics
558 .params
559 .iter()
560 .filter_map(|gp| match gp {
561 GenericParam::Type(TypeParam { ident, .. })
562 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
563 _ => None,
564 })
565 .collect(),
566 impossible: None,
567 must: None,
568 self_ty_can_be_interned: self.self_ty_can_be_interned,
569 };
570 visitor.visit_type(ty);
571 match (visitor.must, visitor.impossible) {
572 (None, None) => Ok(CheckResult::Neutral),
573 (Some((0, span)), None) => Ok(CheckResult::MustIntern(span)),
574 (Some((_, span)), None) => Ok(CheckResult::MustInternOrInherit(span)),
575 (None, Some(span)) => Ok(CheckResult::MustNotIntern(span)),
576 (Some((_, span0)), Some(span1)) => Err((span0, span1)),
577 }
578 }
579
580 pub fn generics(&self) -> &Generics {
581 &self.generics
582 }
583
584 pub fn finish(self) -> Referrer {
586 let leak_types: Vec<_> = self.reachable_types.into_iter().collect();
588 let map = leak_types
589 .iter()
590 .enumerate()
591 .map(|(n, ty)| (ty.clone(), n))
592 .collect();
593 Referrer { leak_types, map }
594 }
595
596 #[cfg_attr(doc, aquamarine::aquamarine)]
597 pub fn reduce_roots(&mut self) {
666 if let Some(operations) = self.pending_operations.take() {
667 self.build_graph_and_reduce(operations);
668 }
669 self.reduce_unreachable_nodes();
670 self.reduce_obvious_nodes();
671 }
672
673 fn build_graph_and_reduce(&mut self, operations: Vec<GraphOperation>) {
674 let mut children: HashMap<Type, Vec<Type>> = HashMap::new();
676 let mut parents: HashMap<Type, Vec<Type>> = HashMap::new();
677 let mut root_types = HashSet::new();
678 let mut must_intern_types = HashSet::new();
679
680 for operation in &operations {
681 if operation.is_root {
682 root_types.insert(operation.node_type.clone());
683 }
684 if operation.is_must_intern {
685 must_intern_types.insert(operation.node_type.clone());
686 }
687
688 if let Some(parent_type) = &operation.parent {
689 children
690 .entry(parent_type.clone())
691 .or_default()
692 .push(operation.node_type.clone());
693 parents
694 .entry(operation.node_type.clone())
695 .or_default()
696 .push(parent_type.clone());
697 }
698 }
699
700 let mut kept_types = HashSet::new();
706
707 for root_type in &root_types {
709 if must_intern_types.contains(root_type) {
710 kept_types.insert(root_type.clone());
711 }
712 }
713
714 for root_type in &root_types {
716 if !kept_types.contains(root_type) {
717 if self.contains_must_intern_descendant(root_type, &children, &must_intern_types) {
718 kept_types.insert(root_type.clone());
719 }
720 }
721 }
722
723 for must_intern_type in &must_intern_types {
725 if !self.is_component_of_any_kept_type(must_intern_type, &kept_types, &children) {
726 kept_types.insert(must_intern_type.clone());
727 }
728 }
729
730 self.reachable_types = kept_types;
731 }
732
733 fn contains_must_intern_descendant(
734 &self,
735 root: &Type,
736 children: &HashMap<Type, Vec<Type>>,
737 must_intern_types: &HashSet<Type>,
738 ) -> bool {
739 let mut visited = HashSet::new();
740 let mut stack = vec![root.clone()];
741
742 while let Some(current) = stack.pop() {
743 if !visited.insert(current.clone()) {
744 continue;
745 }
746
747 if must_intern_types.contains(¤t) {
748 return true;
749 }
750
751 if let Some(child_list) = children.get(¤t) {
752 for child in child_list {
753 if !visited.contains(child) {
754 stack.push(child.clone());
755 }
756 }
757 }
758 }
759
760 false
761 }
762
763 fn is_component_of_any_kept_type(
764 &self,
765 target_type: &Type,
766 kept_types: &HashSet<Type>,
767 children: &HashMap<Type, Vec<Type>>,
768 ) -> bool {
769 for kept_type in kept_types {
770 if self.is_descendant_of(target_type, kept_type, children) {
771 return true;
772 }
773 }
774 false
775 }
776
777 fn is_descendant_of(
778 &self,
779 target: &Type,
780 ancestor: &Type,
781 children: &HashMap<Type, Vec<Type>>,
782 ) -> bool {
783 if target == ancestor {
784 return false; }
786
787 let mut visited = HashSet::new();
788 let mut stack = vec![ancestor.clone()];
789
790 while let Some(current) = stack.pop() {
791 if !visited.insert(current.clone()) {
792 continue;
793 }
794
795 if let Some(child_list) = children.get(¤t) {
796 for child in child_list {
797 if child == target {
798 return true;
799 }
800 if !visited.contains(child) {
801 stack.push(child.clone());
802 }
803 }
804 }
805 }
806
807 false
808 }
809
810 fn reduce_obvious_nodes(&mut self) {
811 }
814
815 fn reduce_unreachable_nodes(&mut self) {
816 if let Some(operations) = self.pending_operations.take() {
817 self.apply_vecgraph_reduction(operations);
818 }
819 }
820
821 fn apply_vecgraph_reduction(&mut self, operations: Vec<GraphOperation>) {
822 let mut root_types = HashSet::new();
823 let mut must_intern_types = HashSet::new();
824
825 for operation in &operations {
827 if operation.is_root {
828 root_types.insert(operation.node_type.clone());
829 }
830 if operation.is_must_intern {
831 must_intern_types.insert(operation.node_type.clone());
832 }
833 }
834
835 self.graph.scope_mut(|mut ctx| {
837 let mut type_to_node = HashMap::new();
838
839 for operation in &operations {
841 if !type_to_node.contains_key(&operation.node_type) {
842 let node_tag = ctx.add_node(operation.node_type.clone());
843 type_to_node.insert(operation.node_type.clone(), node_tag);
844 }
845
846 if let Some(parent_type) = &operation.parent {
847 if !type_to_node.contains_key(parent_type) {
848 let parent_node_tag = ctx.add_node(parent_type.clone());
849 type_to_node.insert(parent_type.clone(), parent_node_tag);
850 }
851 }
852 }
853
854 for operation in &operations {
856 if let Some(parent_type) = &operation.parent {
857 let parent_node = type_to_node[parent_type];
858 let child_node = type_to_node[&operation.node_type];
859 ctx.add_edge((), parent_node, child_node);
860 }
861 }
862 });
863
864 self.reachable_types =
866 self.analyze_reachable_types(&root_types, &must_intern_types, &operations);
867 }
868
869 fn analyze_reachable_types(
870 &self,
871 root_types: &HashSet<Type>,
872 must_intern_types: &HashSet<Type>,
873 operations: &[GraphOperation],
874 ) -> HashSet<Type> {
875 let mut final_types = HashSet::new();
877
878 for root_type in root_types {
880 if must_intern_types.contains(root_type) {
881 final_types.insert(root_type.clone());
882 }
883 }
884
885 for root_type in root_types {
887 if !final_types.contains(root_type) {
888 if self.contains_must_intern_in_tree(root_type, operations, must_intern_types) {
889 final_types.insert(root_type.clone());
890 }
891 }
892 }
893
894 for must_intern_type in must_intern_types {
896 if !self.is_subcomponent_of_kept_root(must_intern_type, &final_types, operations) {
897 final_types.insert(must_intern_type.clone());
898 }
899 }
900
901 final_types
902 }
903
904 fn contains_must_intern_in_tree(
905 &self,
906 root: &Type,
907 operations: &[GraphOperation],
908 must_intern_types: &HashSet<Type>,
909 ) -> bool {
910 let mut stack = vec![root.clone()];
911 let mut visited = HashSet::new();
912
913 while let Some(current) = stack.pop() {
914 if !visited.insert(current.clone()) {
915 continue;
916 }
917
918 if must_intern_types.contains(¤t) {
919 return true;
920 }
921
922 for operation in operations {
923 if let Some(parent_type) = &operation.parent {
924 if parent_type == ¤t && !visited.contains(&operation.node_type) {
925 stack.push(operation.node_type.clone());
926 }
927 }
928 }
929 }
930
931 false
932 }
933
934 fn is_subcomponent_of_kept_root(
935 &self,
936 target: &Type,
937 kept_roots: &HashSet<Type>,
938 operations: &[GraphOperation],
939 ) -> bool {
940 for root in kept_roots {
941 if self.contains_must_intern_in_tree(root, operations, &HashSet::from([target.clone()]))
942 && root != target
943 {
944 return true;
945 }
946 }
947 false
948 }
949
950 }
952
953#[derive(Clone, PartialEq, Eq, Debug)]
958pub struct Referrer {
959 leak_types: Vec<Type>,
960 map: HashMap<Type, usize>,
961}
962
963impl Referrer {
964 pub fn is_empty(&self) -> bool {
966 self.leak_types.is_empty()
967 }
968
969 pub fn iter(&self) -> impl Iterator<Item = &Type> {
980 self.leak_types.iter()
981 }
982
983 pub fn into_visitor<F: FnMut(Type, usize) -> Type>(self, type_fn: F) -> Visitor<F> {
989 Visitor(self, Rc::new(RefCell::new(type_fn)))
990 }
991
992 pub fn expand(&self, ty: Type, type_fn: impl FnMut(Type, usize) -> Type) -> Type {
1004 use syn::fold::Fold;
1005 struct Folder<'a, F>(&'a Referrer, F);
1006 impl<'a, F: FnMut(Type, usize) -> Type> Fold for Folder<'a, F> {
1007 fn fold_type(&mut self, ty: Type) -> Type {
1008 if let Some(idx) = self.0.map.get(&ty) {
1009 self.1(ty, *idx)
1010 } else {
1011 syn::fold::fold_type(self, ty)
1012 }
1013 }
1014 }
1015 let mut folder = Folder(self, type_fn);
1016 folder.fold_type(ty)
1017 }
1018}
1019
1020#[derive(Debug)]
1021pub struct Visitor<F>(Referrer, Rc<RefCell<F>>);
1022
1023impl<F> Clone for Visitor<F> {
1024 fn clone(&self) -> Self {
1025 Self(self.0.clone(), self.1.clone())
1026 }
1027}
1028
1029impl<F: FnMut(Type, usize) -> Type> Visitor<F> {
1030 fn with_generics(&mut self, generics: &mut Generics) -> Self {
1031 let mut visitor = self.clone();
1032 for gp in generics.params.iter_mut() {
1033 if let GenericParam::Type(TypeParam { ident, .. }) = gp {
1034 visitor.0.map.remove(&parse_quote!(#ident));
1035 }
1036 visitor.visit_generic_param_mut(gp);
1037 }
1038 visitor
1039 }
1040
1041 fn with_signature(&mut self, sig: &mut Signature) -> Self {
1042 let mut visitor = self.with_generics(&mut sig.generics);
1043 for input in sig.inputs.iter_mut() {
1044 visitor.visit_fn_arg_mut(input);
1045 }
1046 visitor.visit_return_type_mut(&mut sig.output);
1047 visitor
1048 }
1049}
1050
1051impl<F: FnMut(Type, usize) -> Type> VisitMut for Visitor<F> {
1052 fn visit_type_mut(&mut self, i: &mut Type) {
1053 *i = self.0.expand(i.clone(), &mut *self.1.borrow_mut());
1054 }
1055 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
1056 for attr in i.attrs.iter_mut() {
1057 self.visit_attribute_mut(attr);
1058 }
1059 let mut visitor = self.with_generics(&mut i.generics);
1060 visitor.visit_fields_mut(&mut i.fields);
1061 }
1062 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
1063 for attr in i.attrs.iter_mut() {
1064 self.visit_attribute_mut(attr);
1065 }
1066 let mut visitor = self.with_generics(&mut i.generics);
1067 for variant in i.variants.iter_mut() {
1068 visitor.visit_variant_mut(variant);
1069 }
1070 }
1071 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
1072 for attr in i.attrs.iter_mut() {
1073 self.visit_attribute_mut(attr);
1074 }
1075 let mut visitor = self.with_generics(&mut i.generics);
1076 for supertrait in i.supertraits.iter_mut() {
1077 visitor.visit_type_param_bound_mut(supertrait);
1078 }
1079 for item in i.items.iter_mut() {
1080 visitor.visit_trait_item_mut(item);
1081 }
1082 }
1083 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
1084 for attr in i.attrs.iter_mut() {
1085 self.visit_attribute_mut(attr);
1086 }
1087 let mut visitor = self.with_generics(&mut i.generics);
1088 visitor.visit_fields_named_mut(&mut i.fields);
1089 }
1090 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
1091 for attr in i.attrs.iter_mut() {
1092 self.visit_attribute_mut(attr);
1093 }
1094 let mut visitor = self.with_generics(&mut i.generics);
1095 visitor.visit_type_mut(&mut i.ty);
1096 }
1097 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
1098 for attr in i.attrs.iter_mut() {
1099 self.visit_attribute_mut(attr);
1100 }
1101 let mut visitor = self.with_signature(&mut i.sig);
1102 visitor.visit_block_mut(i.block.as_mut());
1103 }
1104 fn visit_trait_item_fn_mut(&mut self, i: &mut TraitItemFn) {
1105 for attr in i.attrs.iter_mut() {
1106 self.visit_attribute_mut(attr);
1107 }
1108 let mut visitor = self.with_signature(&mut i.sig);
1109 if let Some(block) = &mut i.default {
1110 visitor.visit_block_mut(block);
1111 }
1112 }
1113 fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
1114 for attr in i.attrs.iter_mut() {
1115 self.visit_attribute_mut(attr);
1116 }
1117 let mut visitor = self.with_generics(&mut i.generics);
1118 for bound in i.bounds.iter_mut() {
1119 visitor.visit_type_param_bound_mut(bound);
1120 }
1121 if let Some((_, ty)) = &mut i.default {
1122 visitor.visit_type_mut(ty);
1123 }
1124 }
1125 fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
1126 for attr in i.attrs.iter_mut() {
1127 self.visit_attribute_mut(attr);
1128 }
1129 let mut visitor = self.with_generics(&mut i.generics);
1130 visitor.visit_type_mut(&mut i.ty);
1131 if let Some((_, expr)) = &mut i.default {
1132 visitor.visit_expr_mut(expr);
1133 }
1134 }
1135 fn visit_block_mut(&mut self, i: &mut Block) {
1136 let mut visitor = self.clone();
1137 for stmt in &i.stmts {
1138 match stmt {
1139 Stmt::Item(Item::Struct(ItemStruct { ident, .. }))
1140 | Stmt::Item(Item::Enum(ItemEnum { ident, .. }))
1141 | Stmt::Item(Item::Union(ItemUnion { ident, .. }))
1142 | Stmt::Item(Item::Trait(ItemTrait { ident, .. }))
1143 | Stmt::Item(Item::Type(ItemType { ident, .. })) => {
1144 visitor.0.map.remove(&parse_quote!(#ident));
1145 }
1146 _ => (),
1147 }
1148 }
1149 for stmt in i.stmts.iter_mut() {
1150 visitor.visit_stmt_mut(stmt);
1151 }
1152 }
1153}
1154
1155impl Parse for Referrer {
1156 fn parse(input: parse::ParseStream) -> Result<Self> {
1157 let content: syn::parse::ParseBuffer<'_>;
1158 parenthesized!(content in input);
1159 let leak_types: Vec<Type> = Punctuated::<Type, Token![,]>::parse_terminated(&content)?
1160 .into_iter()
1161 .collect();
1162 let map = leak_types
1163 .iter()
1164 .enumerate()
1165 .map(|(n, ty)| (ty.clone(), n))
1166 .collect();
1167 Ok(Self { map, leak_types })
1168 }
1169}
1170
1171impl ToTokens for Referrer {
1172 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1173 tokens.extend(quote! {
1174 (
1175 #(for item in &self.leak_types), {
1176 #item
1177 }
1178 )
1179 })
1180 }
1181}