cxx_build/syntax/
signature.rs1use crate::syntax::set::{OrderedSet, UnorderedSet};
2use crate::syntax::{FnKind, Receiver, Signature, Type};
3use proc_macro2::Ident;
4use syn::Lifetime;
5
6impl Signature {
7 pub fn receiver(&self) -> Option<&Receiver> {
8 match &self.kind {
9 FnKind::Method(receiver) => Some(receiver),
10 FnKind::Assoc(_) | FnKind::Free => None,
11 }
12 }
13
14 pub fn receiver_mut(&mut self) -> Option<&mut Receiver> {
15 match &mut self.kind {
16 FnKind::Method(receiver) => Some(receiver),
17 FnKind::Assoc(_) | FnKind::Free => None,
18 }
19 }
20
21 pub fn self_type(&self) -> Option<&Ident> {
22 match &self.kind {
23 FnKind::Method(receiver) => Some(&receiver.ty.rust),
24 FnKind::Assoc(self_type) => Some(self_type),
25 FnKind::Free => None,
26 }
27 }
28
29 #[cfg_attr(not(proc_macro), allow(dead_code))]
30 pub fn undeclared_lifetimes<'a>(&'a self) -> OrderedSet<&'a Lifetime> {
31 let mut declared_lifetimes = UnorderedSet::new();
32 for param in self.generics.lifetimes() {
33 declared_lifetimes.insert(¶m.lifetime);
34 }
35
36 let mut undeclared_lifetimes = OrderedSet::new();
37 let mut collect_lifetime = |lifetime: &'a Lifetime| {
38 if lifetime.ident != "_"
39 && lifetime.ident != "static"
40 && !declared_lifetimes.contains(lifetime)
41 {
42 undeclared_lifetimes.insert(lifetime);
43 }
44 };
45
46 match &self.kind {
47 FnKind::Method(receiver) => {
48 if let Some(lifetime) = &receiver.lifetime {
49 collect_lifetime(lifetime);
50 }
51 for lifetime in &receiver.ty.generics.lifetimes {
52 collect_lifetime(lifetime);
53 }
54 }
55 FnKind::Assoc(self_type) => {
56 let _: &Ident = self_type;
59 }
60 FnKind::Free => {}
61 }
62
63 fn collect_type<'a>(collect_lifetime: &mut impl FnMut(&'a Lifetime), ty: &'a Type) {
64 match ty {
65 Type::Ident(named_type) => {
66 for lifetime in &named_type.generics.lifetimes {
67 collect_lifetime(lifetime);
68 }
69 }
70 Type::RustBox(ty1)
71 | Type::RustVec(ty1)
72 | Type::UniquePtr(ty1)
73 | Type::SharedPtr(ty1)
74 | Type::WeakPtr(ty1)
75 | Type::CxxVector(ty1) => collect_type(collect_lifetime, &ty1.inner),
76 Type::Ref(ty) | Type::Str(ty) => {
77 if let Some(lifetime) = &ty.lifetime {
78 collect_lifetime(lifetime);
79 }
80 collect_type(collect_lifetime, &ty.inner);
81 }
82 Type::Ptr(ty) => collect_type(collect_lifetime, &ty.inner),
83 Type::Fn(signature) => {
84 for lifetime in signature.undeclared_lifetimes() {
85 collect_lifetime(lifetime);
86 }
87 }
88 Type::Void(_) => {}
89 Type::SliceRef(ty) => {
90 if let Some(lifetime) = &ty.lifetime {
91 collect_lifetime(lifetime);
92 }
93 collect_type(collect_lifetime, &ty.inner);
94 }
95 Type::Array(ty) => collect_type(collect_lifetime, &ty.inner),
96 }
97 }
98
99 for arg in &self.args {
100 collect_type(&mut collect_lifetime, &arg.ty);
101 }
102
103 if let Some(ret) = &self.ret {
104 collect_type(&mut collect_lifetime, ret);
105 }
106
107 undeclared_lifetimes
108 }
109}