1use crate::{
2 Function, FunctionKind, InterfaceId, Resolve, Type, TypeDef, TypeDefKind, TypeId, WorldId,
3 WorldItem,
4};
5use indexmap::IndexSet;
6
7#[derive(Default)]
8pub struct LiveTypes {
9 set: IndexSet<TypeId>,
10}
11
12impl LiveTypes {
13 pub fn iter(&self) -> impl Iterator<Item = TypeId> + '_ {
14 self.set.iter().copied()
15 }
16
17 pub fn len(&self) -> usize {
18 self.set.len()
19 }
20
21 pub fn contains(&self, id: TypeId) -> bool {
22 self.set.contains(&id)
23 }
24
25 pub fn add_interface(&mut self, resolve: &Resolve, iface: InterfaceId) {
26 self.visit_interface(resolve, iface);
27 }
28
29 pub fn add_world(&mut self, resolve: &Resolve, world: WorldId) {
30 self.visit_world(resolve, world);
31 }
32
33 pub fn add_world_item(&mut self, resolve: &Resolve, item: &WorldItem) {
34 self.visit_world_item(resolve, item);
35 }
36
37 pub fn add_func(&mut self, resolve: &Resolve, func: &Function) {
38 self.visit_func(resolve, func);
39 }
40
41 pub fn add_type_id(&mut self, resolve: &Resolve, ty: TypeId) {
42 self.visit_type_id(resolve, ty);
43 }
44
45 pub fn add_type(&mut self, resolve: &Resolve, ty: &Type) {
46 self.visit_type(resolve, ty);
47 }
48}
49
50impl TypeIdVisitor for LiveTypes {
51 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
52 !self.set.contains(&id)
53 }
54
55 fn after_visit_type_id(&mut self, id: TypeId) {
56 assert!(self.set.insert(id));
57 }
58}
59
60pub trait TypeIdVisitor {
63 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
68 let _ = id;
69 true
70 }
71
72 fn after_visit_type_id(&mut self, id: TypeId) {
74 let _ = id;
75 }
76
77 fn visit_interface(&mut self, resolve: &Resolve, iface: InterfaceId) {
78 let iface = &resolve.interfaces[iface];
79 for (_, id) in iface.types.iter() {
80 self.visit_type_id(resolve, *id);
81 }
82 for (_, func) in iface.functions.iter() {
83 self.visit_func(resolve, func);
84 }
85 }
86
87 fn visit_world(&mut self, resolve: &Resolve, world: WorldId) {
88 let world = &resolve.worlds[world];
89 for (_, item) in world.imports.iter().chain(world.exports.iter()) {
90 self.visit_world_item(resolve, item);
91 }
92 }
93
94 fn visit_world_item(&mut self, resolve: &Resolve, item: &WorldItem) {
95 match item {
96 WorldItem::Interface { id, .. } => self.visit_interface(resolve, *id),
97 WorldItem::Function(f) => self.visit_func(resolve, f),
98 WorldItem::Type(t) => self.visit_type_id(resolve, *t),
99 }
100 }
101
102 fn visit_func(&mut self, resolve: &Resolve, func: &Function) {
103 match func.kind {
104 FunctionKind::Static(id) | FunctionKind::AsyncStatic(id) => {
108 self.visit_type_id(resolve, id)
109 }
110
111 FunctionKind::Method(_)
114 | FunctionKind::AsyncMethod(_)
115 | FunctionKind::Constructor(_) => {}
116
117 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {}
118 }
119
120 for (_, ty) in func.params.iter() {
121 self.visit_type(resolve, ty);
122 }
123 if let Some(ty) = &func.result {
124 self.visit_type(resolve, ty);
125 }
126 }
127
128 fn visit_type_id(&mut self, resolve: &Resolve, ty: TypeId) {
129 if self.before_visit_type_id(ty) {
130 self.visit_type_def(resolve, &resolve.types[ty]);
131 self.after_visit_type_id(ty);
132 }
133 }
134
135 fn visit_type_def(&mut self, resolve: &Resolve, ty: &TypeDef) {
136 match &ty.kind {
137 TypeDefKind::Type(t)
138 | TypeDefKind::List(t)
139 | TypeDefKind::FixedSizeList(t, ..)
140 | TypeDefKind::Option(t)
141 | TypeDefKind::Future(Some(t))
142 | TypeDefKind::Stream(Some(t)) => self.visit_type(resolve, t),
143 TypeDefKind::Handle(handle) => match handle {
144 crate::Handle::Own(ty) => self.visit_type_id(resolve, *ty),
145 crate::Handle::Borrow(ty) => self.visit_type_id(resolve, *ty),
146 },
147 TypeDefKind::Resource => {}
148 TypeDefKind::Record(r) => {
149 for field in r.fields.iter() {
150 self.visit_type(resolve, &field.ty);
151 }
152 }
153 TypeDefKind::Tuple(r) => {
154 for ty in r.types.iter() {
155 self.visit_type(resolve, ty);
156 }
157 }
158 TypeDefKind::Variant(v) => {
159 for case in v.cases.iter() {
160 if let Some(ty) = &case.ty {
161 self.visit_type(resolve, ty);
162 }
163 }
164 }
165 TypeDefKind::Result(r) => {
166 if let Some(ty) = &r.ok {
167 self.visit_type(resolve, ty);
168 }
169 if let Some(ty) = &r.err {
170 self.visit_type(resolve, ty);
171 }
172 }
173 TypeDefKind::Flags(_)
174 | TypeDefKind::Enum(_)
175 | TypeDefKind::Future(None)
176 | TypeDefKind::Stream(None) => {}
177 TypeDefKind::Unknown => unreachable!(),
178 }
179 }
180
181 fn visit_type(&mut self, resolve: &Resolve, ty: &Type) {
182 match ty {
183 Type::Id(id) => self.visit_type_id(resolve, *id),
184 _ => {}
185 }
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::{LiveTypes, Resolve};
192
193 fn live(wit: &str, ty: &str) -> Vec<String> {
194 let mut resolve = Resolve::default();
195 resolve.push_str("test.wit", wit).unwrap();
196 let (_, interface) = resolve.interfaces.iter().next_back().unwrap();
197 let ty = interface.types[ty];
198 let mut live = LiveTypes::default();
199 live.add_type_id(&resolve, ty);
200
201 live.iter()
202 .filter_map(|ty| resolve.types[ty].name.clone())
203 .collect()
204 }
205
206 #[test]
207 fn no_deps() {
208 let types = live(
209 "
210 package foo:bar;
211
212 interface foo {
213 type t = u32;
214 }
215 ",
216 "t",
217 );
218 assert_eq!(types, ["t"]);
219 }
220
221 #[test]
222 fn one_dep() {
223 let types = live(
224 "
225 package foo:bar;
226
227 interface foo {
228 type t = u32;
229 type u = t;
230 }
231 ",
232 "u",
233 );
234 assert_eq!(types, ["t", "u"]);
235 }
236
237 #[test]
238 fn chain() {
239 let types = live(
240 "
241 package foo:bar;
242
243 interface foo {
244 resource t1;
245 record t2 {
246 x: t1,
247 }
248 variant t3 {
249 x(t2),
250 }
251 flags t4 { a }
252 enum t5 { a }
253 type t6 = tuple<t5, t4, t3>;
254 }
255 ",
256 "t6",
257 );
258 assert_eq!(types, ["t5", "t4", "t1", "t2", "t3", "t6"]);
259 }
260}