1#![doc = include_str!("./README.md")]
2
3use gotgraph::prelude::VecGraph;
4use gotgraph::graph::{Graph as GotGraph, GraphUpdate};
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_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
62#[derive(Clone, Debug)]
64pub enum CheckResult {
65 MustIntern(Span),
67 MustInternOrInherit(Span),
70 MustNotIntern(Span),
73 Neutral,
75}
76
77#[derive(Debug, Clone)]
78struct GraphOperation {
79 node_type: Type,
80 parent: Option<Type>,
81 is_root: bool,
82 is_must_intern: bool,
83}
84
85struct AnalyzeVisitor<'a> {
86 leaker: &'a mut Leaker,
87 generics: Generics,
88 parent: Option<Type>,
89 error: Option<Span>,
90 operations: Vec<GraphOperation>,
91}
92
93impl<'a, 'ast> Visit<'ast> for AnalyzeVisitor<'a> {
94 fn visit_trait_item_fn(&mut self, i: &TraitItemFn) {
95 let mut visitor = AnalyzeVisitor {
96 leaker: &mut self.leaker,
97 generics: self.generics.clone(),
98 parent: self.parent.clone(),
99 error: self.error.clone(),
100 operations: Vec::new(),
101 };
102 for g in &i.sig.generics.params {
103 visitor.generics.params.push(g.clone());
104 }
105 let mut i = i.clone();
106 i.default = None;
107 i.semi_token = Some(Default::default());
108 syn::visit::visit_trait_item_fn(&mut visitor, &mut i);
109 self.error = visitor.error;
110 self.operations.extend(visitor.operations);
111 }
112
113 fn visit_receiver(&mut self, i: &Receiver) {
114 for attr in &i.attrs {
115 self.visit_attribute(attr);
116 }
117 if let Some((_, Some(lt))) = &i.reference {
118 self.visit_lifetime(lt);
119 }
120 if i.colon_token.is_some() {
121 self.visit_type(&i.ty);
122 }
123 }
124
125 fn visit_trait_item_type(&mut self, i: &TraitItemType) {
126 let mut visitor = AnalyzeVisitor {
127 leaker: &mut self.leaker,
128 generics: self.generics.clone(),
129 parent: self.parent.clone(),
130 error: self.error.clone(),
131 operations: Vec::new(),
132 };
133 for g in &i.generics.params {
134 visitor.generics.params.push(g.clone());
135 }
136 syn::visit::visit_trait_item_type(&mut visitor, i);
137 self.error = visitor.error;
138 self.operations.extend(visitor.operations);
139 }
140
141 fn visit_type(&mut self, i: &Type) {
142 match self.leaker.check(&self.generics, i) {
143 Err((_, s)) => {
144 self.error = Some(s);
146 }
147 Ok(CheckResult::MustNotIntern(_)) => (),
148 o => {
149 let is_must_intern = matches!(o, Ok(CheckResult::MustIntern(_)));
151 let is_root = self.parent.is_none();
152
153 self.operations.push(GraphOperation {
154 node_type: i.clone(),
155 parent: self.parent.clone(),
156 is_root,
157 is_must_intern,
158 });
159
160 if !is_must_intern {
161 let parent = self.parent.clone();
163 self.parent = Some(i.clone());
164 syn::visit::visit_type(self, i);
165 self.parent = parent;
166 }
167 }
168 }
169 }
170
171 fn visit_trait_bound(&mut self, i: &TraitBound) {
172 if i.path.leading_colon.is_none() {
173 self.error = Some(i.span());
175 } else {
176 syn::visit::visit_trait_bound(self, i)
177 }
178 }
179
180 fn visit_expr_path(&mut self, i: &ExprPath) {
181 if i.path.leading_colon.is_none() {
182 self.error = Some(i.span());
184 } else {
185 syn::visit::visit_expr_path(self, i)
186 }
187 }
188}
189
190impl Leaker {
191 pub fn from_struct(input: &ItemStruct) -> std::result::Result<Self, NotInternableError> {
206 let mut leaker = Leaker::with_generics(input.generics.clone());
207 let mut visitor = AnalyzeVisitor {
208 leaker: &mut leaker,
209 parent: None,
210 error: None,
211 generics: input.generics.clone(),
212 operations: Vec::new(),
213 };
214 visitor.visit_item_struct(input);
215 if let Some(e) = visitor.error {
216 return Err(NotInternableError(e));
217 }
218 let operations = visitor.operations;
219 leaker.apply_operations(operations);
220 Ok(leaker)
221 }
222
223 pub fn from_enum(input: &ItemEnum) -> std::result::Result<Self, NotInternableError> {
225 let mut leaker = Self::with_generics(input.generics.clone());
226 let mut visitor = AnalyzeVisitor {
227 leaker: &mut leaker,
228 parent: None,
229 error: None,
230 generics: input.generics.clone(),
231 operations: Vec::new(),
232 };
233 visitor.visit_item_enum(input);
234 if let Some(e) = visitor.error {
235 return Err(NotInternableError(e));
236 }
237 let operations = visitor.operations;
238 leaker.apply_operations(operations);
239 Ok(leaker)
240 }
241
242 pub fn from_trait(input: &ItemTrait) -> std::result::Result<Self, NotInternableError> {
263 let mut leaker = Self::with_generics(input.generics.clone());
264 let mut visitor = AnalyzeVisitor {
265 leaker: &mut leaker,
266 parent: None,
267 error: None,
268 generics: input.generics.clone(),
269 operations: Vec::new(),
270 };
271 visitor.visit_item_trait(input);
272 if let Some(e) = visitor.error {
273 return Err(NotInternableError(e));
274 }
275 let operations = visitor.operations;
276 leaker.apply_operations(operations);
277 Ok(leaker)
278 }
279
280 pub fn with_generics(generics: Generics) -> Self {
285 Self {
286 generics,
287 graph: VecGraph::default(),
288 self_ty_can_be_interned: true,
289 reachable_types: HashSet::new(),
290 pending_operations: None,
291 }
292 }
293
294 fn apply_operations(&mut self, operations: Vec<GraphOperation>) {
296 if operations.is_empty() {
297 return;
298 }
299
300 self.pending_operations = Some(operations);
302 }
303
304 pub fn intern(
306 &mut self,
307 generics: Generics,
308 ty: &Type,
309 ) -> std::result::Result<&mut Self, NotInternableError> {
310 let mut visitor = AnalyzeVisitor {
311 leaker: self,
312 parent: None,
313 error: None,
314 generics,
315 operations: Vec::new(),
316 };
317 visitor.visit_type(ty);
318 if let Some(e) = visitor.error {
319 Err(NotInternableError(e))
320 } else {
321 let operations = visitor.operations;
322 self.apply_operations(operations);
323 Ok(self)
324 }
325 }
326
327 pub fn check(
333 &self,
334 generics: &Generics,
335 ty: &Type,
336 ) -> std::result::Result<CheckResult, (Span, Span)> {
337 use syn::visit::Visit;
338 #[derive(Clone)]
339 struct Visitor {
340 generic_lifetimes_base: Vec<Lifetime>,
341 generic_idents_base: Vec<Ident>,
342 generic_lifetimes: Vec<Lifetime>,
343 generic_idents: Vec<Ident>,
344 impossible: Option<Span>,
345 must: Option<(isize, Span)>,
346 self_ty_can_be_interned: bool,
347 }
348
349 const _: () = {
350 use syn::visit::Visit;
351 impl<'a> Visit<'a> for Visitor {
352 fn visit_type(&mut self, i: &Type) {
353 match i {
354 Type::BareFn(TypeBareFn {
355 lifetimes,
356 inputs,
357 output,
358 ..
359 }) => {
360 let mut visitor = self.clone();
361 visitor.must = None;
362 visitor.generic_lifetimes.extend(
363 lifetimes
364 .as_ref()
365 .map(|ls| {
366 ls.lifetimes.iter().map(|gp| {
367 if let GenericParam::Lifetime(lt) = gp {
368 lt.lifetime.clone()
369 } else {
370 panic!()
371 }
372 })
373 })
374 .into_iter()
375 .flatten(),
376 );
377 for input in inputs {
378 visitor.visit_type(&input.ty);
379 }
380 if let ReturnType::Type(_, output) = output {
381 visitor.visit_type(output.as_ref());
382 }
383 if self.impossible.is_none() {
384 self.impossible = visitor.impossible;
385 }
386 match (self.must.clone(), visitor.must.clone()) {
387 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
388 self.must = Some((v_l + 1, v_m))
389 }
390 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
391 _ => (),
392 }
393 return;
394 }
395 Type::TraitObject(TypeTraitObject { bounds, .. }) => {
396 for bound in bounds {
397 match bound {
398 TypeParamBound::Trait(TraitBound {
399 lifetimes, path, ..
400 }) => {
401 let mut visitor = self.clone();
402 visitor.must = None;
403 visitor.generic_lifetimes.extend(
404 lifetimes
405 .as_ref()
406 .map(|ls| {
407 ls.lifetimes.iter().map(|gp| {
408 if let GenericParam::Lifetime(lt) = gp {
409 lt.lifetime.clone()
410 } else {
411 panic!()
412 }
413 })
414 })
415 .into_iter()
416 .flatten(),
417 );
418 visitor.visit_path(path);
419 if self.impossible.is_none() {
420 self.impossible = visitor.impossible;
421 }
422 match (self.must.clone(), visitor.must.clone()) {
423 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
424 self.must = Some((v_l + 1, v_m))
425 }
426 (None, Some((v_l, v_m))) => {
427 self.must = Some((v_l + 1, v_m))
428 }
429 _ => (),
430 }
431 return;
432 }
433 TypeParamBound::Verbatim(_) => {
434 self.impossible = Some(bound.span());
435 return;
436 }
437 _ => (),
438 }
439 }
440 }
441 Type::ImplTrait(_) | Type::Macro(_) | Type::Verbatim(_) => {
442 self.impossible = Some(i.span());
443 }
444 Type::Reference(TypeReference { lifetime, .. }) => {
445 if lifetime.is_none() {
446 self.impossible = Some(i.span());
447 }
448 }
449 _ => (),
450 }
451 let mut visitor = self.clone();
452 visitor.must = None;
453 syn::visit::visit_type(&mut visitor, i);
454 if visitor.impossible.is_some() {
455 self.impossible = visitor.impossible;
456 }
457 match (self.must.clone(), visitor.must.clone()) {
458 (Some((s_l, _)), Some((v_l, v_m))) if v_l + 1 < s_l => {
459 self.must = Some((v_l + 1, v_m))
460 }
461 (None, Some((v_l, v_m))) => self.must = Some((v_l + 1, v_m)),
462 _ => (),
463 }
464 }
465 fn visit_qself(&mut self, i: &QSelf) {
466 if i.as_token.is_none() {
467 self.impossible = Some(i.span());
468 }
469 syn::visit::visit_qself(self, i)
470 }
471 fn visit_lifetime(&mut self, i: &Lifetime) {
472 match i.to_string().as_str() {
473 "'static" => (),
474 "'_" => self.impossible = Some(i.span()),
475 _ if self.generic_lifetimes_base.iter().any(|lt| lt == i) => {}
476 _ if self.generic_lifetimes.iter().any(|lt| lt == i) => {
477 self.impossible = Some(i.span());
478 }
479 _ => {
480 self.must = Some((-1, i.span()));
481 }
482 }
483 syn::visit::visit_lifetime(self, i)
484 }
485 fn visit_expr(&mut self, i: &Expr) {
486 match i {
487 Expr::Closure(_) | Expr::Assign(_) | Expr::Verbatim(_) | Expr::Macro(_) => {
488 self.impossible = Some(i.span());
489 }
490 _ => (),
491 }
492 syn::visit::visit_expr(self, i)
493 }
494 fn visit_path(&mut self, i: &Path) {
495 if matches!(i.segments.iter().next(), Some(PathSegment { ident, arguments }) if ident == "Self" && arguments.is_none())
496 && i.leading_colon.is_none()
497 {
498 if !self.self_ty_can_be_interned {
499 self.impossible = Some(i.span());
500 }
501 } else {
502 match (i.leading_colon, i.get_ident()) {
503 (None, Some(ident)) if self.generic_idents_base.contains(&ident) => {}
505 (None, Some(ident)) if self.generic_idents.contains(&ident) => {
506 self.impossible = Some(i.span());
507 }
508 (None, _) => {
510 self.must = Some((-1, i.span()));
511 }
512 (Some(_), _) => (),
514 }
515 }
516 syn::visit::visit_path(self, i)
517 }
518 }
519 };
520 let mut visitor = Visitor {
521 generic_lifetimes_base: self.generics
522 .params
523 .iter()
524 .filter_map(|gp| {
525 if let GenericParam::Lifetime(lt) = gp {
526 Some(lt.lifetime.clone())
527 } else {
528 None
529 }
530 })
531 .collect(),
532 generic_idents_base: self.generics
533 .params
534 .iter()
535 .filter_map(|gp| match gp {
536 GenericParam::Type(TypeParam { ident, .. })
537 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
538 _ => None,
539 })
540 .collect(),
541 generic_lifetimes: generics
542 .params
543 .iter()
544 .filter_map(|gp| {
545 if let GenericParam::Lifetime(lt) = gp {
546 Some(lt.lifetime.clone())
547 } else {
548 None
549 }
550 })
551 .collect(),
552 generic_idents: generics
553 .params
554 .iter()
555 .filter_map(|gp| match gp {
556 GenericParam::Type(TypeParam { ident, .. })
557 | GenericParam::Const(ConstParam { ident, .. }) => Some(ident.clone()),
558 _ => None,
559 })
560 .collect(),
561 impossible: None,
562 must: None,
563 self_ty_can_be_interned: self.self_ty_can_be_interned,
564 };
565 visitor.visit_type(ty);
566 match (visitor.must, visitor.impossible) {
567 (None, None) => Ok(CheckResult::Neutral),
568 (Some((0, span)), None) => Ok(CheckResult::MustIntern(span)),
569 (Some((_, span)), None) => Ok(CheckResult::MustInternOrInherit(span)),
570 (None, Some(span)) => Ok(CheckResult::MustNotIntern(span)),
571 (Some((_, span0)), Some(span1)) => Err((span0, span1)),
572 }
573 }
574
575 pub fn generics(&self) -> &Generics {
576 &self.generics
577 }
578
579 pub fn finish(self) -> Referrer {
581 let leak_types: Vec<_> = self.reachable_types.into_iter().collect();
583 let map = leak_types
584 .iter()
585 .enumerate()
586 .map(|(n, ty)| (ty.clone(), n))
587 .collect();
588 Referrer { leak_types, map }
589 }
590
591 #[cfg_attr(doc, aquamarine::aquamarine)]
592 pub fn reduce_roots(&mut self) {
661 if let Some(operations) = self.pending_operations.take() {
662 self.build_graph_and_reduce(operations);
663 }
664 self.reduce_unreachable_nodes();
665 self.reduce_obvious_nodes();
666 }
667
668 fn build_graph_and_reduce(&mut self, operations: Vec<GraphOperation>) {
669 let mut children: HashMap<Type, Vec<Type>> = HashMap::new();
671 let mut parents: HashMap<Type, Vec<Type>> = HashMap::new();
672 let mut root_types = HashSet::new();
673 let mut must_intern_types = HashSet::new();
674
675 for operation in &operations {
676 if operation.is_root {
677 root_types.insert(operation.node_type.clone());
678 }
679 if operation.is_must_intern {
680 must_intern_types.insert(operation.node_type.clone());
681 }
682
683 if let Some(parent_type) = &operation.parent {
684 children.entry(parent_type.clone()).or_default().push(operation.node_type.clone());
685 parents.entry(operation.node_type.clone()).or_default().push(parent_type.clone());
686 }
687 }
688
689
690 let mut kept_types = HashSet::new();
696
697 for root_type in &root_types {
699 if must_intern_types.contains(root_type) {
700 kept_types.insert(root_type.clone());
701 }
702 }
703
704 for root_type in &root_types {
706 if !kept_types.contains(root_type) {
707 if self.contains_must_intern_descendant(root_type, &children, &must_intern_types) {
708 kept_types.insert(root_type.clone());
709 }
710 }
711 }
712
713 for must_intern_type in &must_intern_types {
715 if !self.is_component_of_any_kept_type(must_intern_type, &kept_types, &children) {
716 kept_types.insert(must_intern_type.clone());
717 }
718 }
719
720 self.reachable_types = kept_types;
721 }
722
723 fn contains_must_intern_descendant(&self, root: &Type, children: &HashMap<Type, Vec<Type>>, must_intern_types: &HashSet<Type>) -> bool {
724 let mut visited = HashSet::new();
725 let mut stack = vec![root.clone()];
726
727 while let Some(current) = stack.pop() {
728 if !visited.insert(current.clone()) {
729 continue;
730 }
731
732 if must_intern_types.contains(¤t) {
733 return true;
734 }
735
736 if let Some(child_list) = children.get(¤t) {
737 for child in child_list {
738 if !visited.contains(child) {
739 stack.push(child.clone());
740 }
741 }
742 }
743 }
744
745 false
746 }
747
748 fn is_component_of_any_kept_type(&self, target_type: &Type, kept_types: &HashSet<Type>, children: &HashMap<Type, Vec<Type>>) -> bool {
749 for kept_type in kept_types {
750 if self.is_descendant_of(target_type, kept_type, children) {
751 return true;
752 }
753 }
754 false
755 }
756
757 fn is_descendant_of(&self, target: &Type, ancestor: &Type, children: &HashMap<Type, Vec<Type>>) -> bool {
758 if target == ancestor {
759 return false; }
761
762 let mut visited = HashSet::new();
763 let mut stack = vec![ancestor.clone()];
764
765 while let Some(current) = stack.pop() {
766 if !visited.insert(current.clone()) {
767 continue;
768 }
769
770 if let Some(child_list) = children.get(¤t) {
771 for child in child_list {
772 if child == target {
773 return true;
774 }
775 if !visited.contains(child) {
776 stack.push(child.clone());
777 }
778 }
779 }
780 }
781
782 false
783 }
784
785 fn reduce_obvious_nodes(&mut self) {
786 }
789
790 fn reduce_unreachable_nodes(&mut self) {
791 if let Some(operations) = self.pending_operations.take() {
792 self.apply_vecgraph_reduction(operations);
793 }
794 }
795
796 fn apply_vecgraph_reduction(&mut self, operations: Vec<GraphOperation>) {
797 let mut root_types = HashSet::new();
798 let mut must_intern_types = HashSet::new();
799
800 for operation in &operations {
802 if operation.is_root {
803 root_types.insert(operation.node_type.clone());
804 }
805 if operation.is_must_intern {
806 must_intern_types.insert(operation.node_type.clone());
807 }
808 }
809
810 self.graph.scope_mut(|mut ctx| {
812 let mut type_to_node = HashMap::new();
813
814 for operation in &operations {
816 if !type_to_node.contains_key(&operation.node_type) {
817 let node_tag = ctx.add_node(operation.node_type.clone());
818 type_to_node.insert(operation.node_type.clone(), node_tag);
819 }
820
821 if let Some(parent_type) = &operation.parent {
822 if !type_to_node.contains_key(parent_type) {
823 let parent_node_tag = ctx.add_node(parent_type.clone());
824 type_to_node.insert(parent_type.clone(), parent_node_tag);
825 }
826 }
827 }
828
829 for operation in &operations {
831 if let Some(parent_type) = &operation.parent {
832 let parent_node = type_to_node[parent_type];
833 let child_node = type_to_node[&operation.node_type];
834 ctx.add_edge((), parent_node, child_node);
835 }
836 }
837 });
838
839 self.reachable_types = self.analyze_reachable_types(&root_types, &must_intern_types, &operations);
841 }
842
843 fn analyze_reachable_types(&self, root_types: &HashSet<Type>, must_intern_types: &HashSet<Type>, operations: &[GraphOperation]) -> HashSet<Type> {
844 let mut final_types = HashSet::new();
846
847 for root_type in root_types {
849 if must_intern_types.contains(root_type) {
850 final_types.insert(root_type.clone());
851 }
852 }
853
854 for root_type in root_types {
856 if !final_types.contains(root_type) {
857 if self.contains_must_intern_in_tree(root_type, operations, must_intern_types) {
858 final_types.insert(root_type.clone());
859 }
860 }
861 }
862
863 for must_intern_type in must_intern_types {
865 if !self.is_subcomponent_of_kept_root(must_intern_type, &final_types, operations) {
866 final_types.insert(must_intern_type.clone());
867 }
868 }
869
870 final_types
871 }
872
873 fn contains_must_intern_in_tree(&self, root: &Type, operations: &[GraphOperation], must_intern_types: &HashSet<Type>) -> bool {
874 let mut stack = vec![root.clone()];
875 let mut visited = HashSet::new();
876
877 while let Some(current) = stack.pop() {
878 if !visited.insert(current.clone()) {
879 continue;
880 }
881
882 if must_intern_types.contains(¤t) {
883 return true;
884 }
885
886 for operation in operations {
887 if let Some(parent_type) = &operation.parent {
888 if parent_type == ¤t && !visited.contains(&operation.node_type) {
889 stack.push(operation.node_type.clone());
890 }
891 }
892 }
893 }
894
895 false
896 }
897
898 fn is_subcomponent_of_kept_root(&self, target: &Type, kept_roots: &HashSet<Type>, operations: &[GraphOperation]) -> bool {
899 for root in kept_roots {
900 if self.contains_must_intern_in_tree(root, operations, &HashSet::from([target.clone()])) && root != target {
901 return true;
902 }
903 }
904 false
905 }
906
907 }
909
910#[derive(Clone, PartialEq, Eq, Debug)]
911pub struct Referrer {
912 leak_types: Vec<Type>,
913 map: HashMap<Type, usize>,
914}
915
916impl Referrer {
917 pub fn is_empty(&self) -> bool {
918 self.leak_types.is_empty()
919 }
920
921 pub fn iter(&self) -> impl Iterator<Item = &Type> {
922 self.leak_types.iter()
923 }
924
925 pub fn into_visitor<F: FnMut(Type, usize) -> Type>(self, type_fn: F) -> Visitor<F> {
926 Visitor(self, Rc::new(RefCell::new(type_fn)))
927 }
928
929 pub fn expand(&self, ty: Type, type_fn: impl FnMut(Type, usize) -> Type) -> Type {
930 use syn::fold::Fold;
931 struct Folder<'a, F>(&'a Referrer, F);
932 impl<'a, F: FnMut(Type, usize) -> Type> Fold for Folder<'a, F> {
933 fn fold_type(&mut self, ty: Type) -> Type {
934 if let Some(idx) = self.0.map.get(&ty) {
935 self.1(ty, *idx)
936 } else {
937 syn::fold::fold_type(self, ty)
938 }
939 }
940 }
941 let mut folder = Folder(self, type_fn);
942 folder.fold_type(ty)
943 }
944}
945
946#[derive(Debug)]
947pub struct Visitor<F>(Referrer, Rc<RefCell<F>>);
948
949impl<F> Clone for Visitor<F> {
950 fn clone(&self) -> Self {
951 Self(self.0.clone(), self.1.clone())
952 }
953}
954
955impl<F: FnMut(Type, usize) -> Type> Visitor<F> {
956 fn with_generics(&mut self, generics: &mut Generics) -> Self {
957 let mut visitor = self.clone();
958 for gp in generics.params.iter_mut() {
959 if let GenericParam::Type(TypeParam { ident, .. }) = gp {
960 visitor.0.map.remove(&parse_quote!(#ident));
961 }
962 visitor.visit_generic_param_mut(gp);
963 }
964 visitor
965 }
966
967 fn with_signature(&mut self, sig: &mut Signature) -> Self {
968 let mut visitor = self.with_generics(&mut sig.generics);
969 for input in sig.inputs.iter_mut() {
970 visitor.visit_fn_arg_mut(input);
971 }
972 visitor.visit_return_type_mut(&mut sig.output);
973 visitor
974 }
975}
976
977impl<F: FnMut(Type, usize) -> Type> VisitMut for Visitor<F> {
978 fn visit_type_mut(&mut self, i: &mut Type) {
979 *i = self.0.expand(i.clone(), &mut *self.1.borrow_mut());
980 }
981 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
982 for attr in i.attrs.iter_mut() {
983 self.visit_attribute_mut(attr);
984 }
985 let mut visitor = self.with_generics(&mut i.generics);
986 visitor.visit_fields_mut(&mut i.fields);
987 }
988 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
989 for attr in i.attrs.iter_mut() {
990 self.visit_attribute_mut(attr);
991 }
992 let mut visitor = self.with_generics(&mut i.generics);
993 for variant in i.variants.iter_mut() {
994 visitor.visit_variant_mut(variant);
995 }
996 }
997 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
998 for attr in i.attrs.iter_mut() {
999 self.visit_attribute_mut(attr);
1000 }
1001 let mut visitor = self.with_generics(&mut i.generics);
1002 for supertrait in i.supertraits.iter_mut() {
1003 visitor.visit_type_param_bound_mut(supertrait);
1004 }
1005 for item in i.items.iter_mut() {
1006 visitor.visit_trait_item_mut(item);
1007 }
1008 }
1009 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
1010 for attr in i.attrs.iter_mut() {
1011 self.visit_attribute_mut(attr);
1012 }
1013 let mut visitor = self.with_generics(&mut i.generics);
1014 visitor.visit_fields_named_mut(&mut i.fields);
1015 }
1016 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
1017 for attr in i.attrs.iter_mut() {
1018 self.visit_attribute_mut(attr);
1019 }
1020 let mut visitor = self.with_generics(&mut i.generics);
1021 visitor.visit_type_mut(&mut i.ty);
1022 }
1023 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
1024 for attr in i.attrs.iter_mut() {
1025 self.visit_attribute_mut(attr);
1026 }
1027 let mut visitor = self.with_signature(&mut i.sig);
1028 visitor.visit_block_mut(i.block.as_mut());
1029 }
1030 fn visit_trait_item_fn_mut(&mut self, i: &mut TraitItemFn) {
1031 for attr in i.attrs.iter_mut() {
1032 self.visit_attribute_mut(attr);
1033 }
1034 let mut visitor = self.with_signature(&mut i.sig);
1035 if let Some(block) = &mut i.default {
1036 visitor.visit_block_mut(block);
1037 }
1038 }
1039 fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
1040 for attr in i.attrs.iter_mut() {
1041 self.visit_attribute_mut(attr);
1042 }
1043 let mut visitor = self.with_generics(&mut i.generics);
1044 for bound in i.bounds.iter_mut() {
1045 visitor.visit_type_param_bound_mut(bound);
1046 }
1047 if let Some((_, ty)) = &mut i.default {
1048 visitor.visit_type_mut(ty);
1049 }
1050 }
1051 fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
1052 for attr in i.attrs.iter_mut() {
1053 self.visit_attribute_mut(attr);
1054 }
1055 let mut visitor = self.with_generics(&mut i.generics);
1056 visitor.visit_type_mut(&mut i.ty);
1057 if let Some((_, expr)) = &mut i.default {
1058 visitor.visit_expr_mut(expr);
1059 }
1060 }
1061 fn visit_block_mut(&mut self, i: &mut Block) {
1062 let mut visitor = self.clone();
1063 for stmt in &i.stmts {
1064 match stmt {
1065 Stmt::Item(Item::Struct(ItemStruct { ident, .. }))
1066 | Stmt::Item(Item::Enum(ItemEnum { ident, .. }))
1067 | Stmt::Item(Item::Union(ItemUnion { ident, .. }))
1068 | Stmt::Item(Item::Trait(ItemTrait { ident, .. }))
1069 | Stmt::Item(Item::Type(ItemType { ident, .. })) => {
1070 visitor.0.map.remove(&parse_quote!(#ident));
1071 }
1072 _ => (),
1073 }
1074 }
1075 for stmt in i.stmts.iter_mut() {
1076 visitor.visit_stmt_mut(stmt);
1077 }
1078 }
1079}
1080
1081impl Parse for Referrer {
1082 fn parse(input: parse::ParseStream) -> Result<Self> {
1083 let content: syn::parse::ParseBuffer<'_>;
1084 parenthesized!(content in input);
1085 let leak_types: Vec<Type> = Punctuated::<Type, Token![,]>::parse_terminated(&content)?
1086 .into_iter()
1087 .collect();
1088 let map = leak_types
1089 .iter()
1090 .enumerate()
1091 .map(|(n, ty)| (ty.clone(), n))
1092 .collect();
1093 Ok(Self { map, leak_types })
1094 }
1095}
1096
1097impl ToTokens for Referrer {
1098 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1099 tokens.extend(quote! {
1100 (
1101 #(for item in &self.leak_types), {
1102 #item
1103 }
1104 )
1105 })
1106 }
1107}