/src/wasm-tools/crates/wit-parser/src/live.rs
Line | Count | Source |
1 | | use crate::{ |
2 | | Function, FunctionKind, IndexSet, InterfaceId, Resolve, Type, TypeDef, TypeDefKind, TypeId, |
3 | | WorldId, WorldItem, |
4 | | }; |
5 | | |
6 | | #[derive(Default)] |
7 | | pub struct LiveTypes { |
8 | | set: IndexSet<TypeId>, |
9 | | } |
10 | | |
11 | | impl LiveTypes { |
12 | 6.22k | pub fn iter(&self) -> impl Iterator<Item = TypeId> + '_ { |
13 | 6.22k | self.set.iter().copied() |
14 | 6.22k | } |
15 | | |
16 | 0 | pub fn len(&self) -> usize { |
17 | 0 | self.set.len() |
18 | 0 | } |
19 | | |
20 | 0 | pub fn contains(&self, id: TypeId) -> bool { |
21 | 0 | self.set.contains(&id) |
22 | 0 | } |
23 | | |
24 | 1.65k | pub fn add_interface(&mut self, resolve: &Resolve, iface: InterfaceId) { |
25 | 1.65k | self.visit_interface(resolve, iface); |
26 | 1.65k | } |
27 | | |
28 | 0 | pub fn add_world(&mut self, resolve: &Resolve, world: WorldId) { |
29 | 0 | self.visit_world(resolve, world); |
30 | 0 | } |
31 | | |
32 | 2.54k | pub fn add_world_item(&mut self, resolve: &Resolve, item: &WorldItem) { |
33 | 2.54k | self.visit_world_item(resolve, item); |
34 | 2.54k | } |
35 | | |
36 | 934 | pub fn add_func(&mut self, resolve: &Resolve, func: &Function) { |
37 | 934 | self.visit_func(resolve, func); |
38 | 934 | } |
39 | | |
40 | 3.24k | pub fn add_type_id(&mut self, resolve: &Resolve, ty: TypeId) { |
41 | 3.24k | self.visit_type_id(resolve, ty); |
42 | 3.24k | } |
43 | | |
44 | 742 | pub fn add_type(&mut self, resolve: &Resolve, ty: &Type) { |
45 | 742 | self.visit_type(resolve, ty); |
46 | 742 | } |
47 | | } |
48 | | |
49 | | impl TypeIdVisitor for LiveTypes { |
50 | 36.4k | fn before_visit_type_id(&mut self, id: TypeId) -> bool { |
51 | 36.4k | !self.set.contains(&id) |
52 | 36.4k | } |
53 | | |
54 | 29.7k | fn after_visit_type_id(&mut self, id: TypeId) { |
55 | 29.7k | assert!(self.set.insert(id)); |
56 | 29.7k | } |
57 | | } |
58 | | |
59 | | /// Helper trait to walk the structure of a type and visit all `TypeId`s that |
60 | | /// it refers to, possibly transitively. |
61 | | pub trait TypeIdVisitor { |
62 | | /// Callback invoked just before a type is visited. |
63 | | /// |
64 | | /// If this function returns `false` the type is not visited, otherwise it's |
65 | | /// recursed into. |
66 | 0 | fn before_visit_type_id(&mut self, id: TypeId) -> bool { |
67 | 0 | let _ = id; |
68 | 0 | true |
69 | 0 | } |
70 | | |
71 | | /// Callback invoked once a type is finished being visited. |
72 | 8.35k | fn after_visit_type_id(&mut self, id: TypeId) { |
73 | 8.35k | let _ = id; |
74 | 8.35k | } |
75 | | |
76 | 3.30k | fn visit_interface(&mut self, resolve: &Resolve, iface: InterfaceId) { |
77 | 3.30k | let iface = &resolve.interfaces[iface]; |
78 | 14.8k | for (_, id) in iface.types.iter() { |
79 | 14.8k | self.visit_type_id(resolve, *id); |
80 | 14.8k | } |
81 | 5.21k | for (_, func) in iface.functions.iter() { |
82 | 5.21k | self.visit_func(resolve, func); |
83 | 5.21k | } |
84 | 3.30k | } |
85 | | |
86 | 0 | fn visit_world(&mut self, resolve: &Resolve, world: WorldId) { |
87 | 0 | let world = &resolve.worlds[world]; |
88 | 0 | for (_, item) in world.imports.iter().chain(world.exports.iter()) { |
89 | 0 | self.visit_world_item(resolve, item); |
90 | 0 | } |
91 | 0 | } |
92 | | |
93 | 2.54k | fn visit_world_item(&mut self, resolve: &Resolve, item: &WorldItem) { |
94 | 2.54k | match item { |
95 | 1.65k | WorldItem::Interface { id, .. } => self.visit_interface(resolve, *id), |
96 | 898 | WorldItem::Function(f) => self.visit_func(resolve, f), |
97 | 0 | WorldItem::Type { id, .. } => self.visit_type_id(resolve, *id), |
98 | | } |
99 | 2.54k | } |
100 | | |
101 | 7.04k | fn visit_func(&mut self, resolve: &Resolve, func: &Function) { |
102 | 7.04k | match func.kind { |
103 | | // This resource is live as it's attached to a static method but |
104 | | // it's not guaranteed to be present in either params or results, so |
105 | | // be sure to attach it here. |
106 | 1.30k | FunctionKind::Static(id) | FunctionKind::AsyncStatic(id) => { |
107 | 1.37k | self.visit_type_id(resolve, id) |
108 | | } |
109 | | |
110 | | // The resource these are attached to is in the params/results, so |
111 | | // no need to re-add it here. |
112 | | FunctionKind::Method(_) |
113 | | | FunctionKind::AsyncMethod(_) |
114 | 735 | | FunctionKind::Constructor(_) => {} |
115 | | |
116 | 4.93k | FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {} |
117 | | } |
118 | | |
119 | 14.1k | for param in func.params.iter() { |
120 | 14.1k | self.visit_type(resolve, ¶m.ty); |
121 | 14.1k | } |
122 | 7.04k | if let Some(ty) = &func.result { |
123 | 6.31k | self.visit_type(resolve, ty); |
124 | 6.31k | } |
125 | 7.04k | } |
126 | | |
127 | 45.4k | fn visit_type_id(&mut self, resolve: &Resolve, ty: TypeId) { |
128 | 45.4k | if self.before_visit_type_id(ty) { |
129 | 38.0k | self.visit_type_def(resolve, &resolve.types[ty]); |
130 | 38.0k | self.after_visit_type_id(ty); |
131 | 38.0k | } |
132 | 45.4k | } <<wit_parser::resolve::Resolve>::assert_world_imports_type_deps::MyVisit as wit_parser::live::TypeIdVisitor>::visit_type_id Line | Count | Source | 127 | 8.97k | fn visit_type_id(&mut self, resolve: &Resolve, ty: TypeId) { | 128 | 8.97k | if self.before_visit_type_id(ty) { | 129 | 8.35k | self.visit_type_def(resolve, &resolve.types[ty]); | 130 | 8.35k | self.after_visit_type_id(ty); | 131 | 8.35k | } | 132 | 8.97k | } |
<wit_parser::live::LiveTypes as wit_parser::live::TypeIdVisitor>::visit_type_id Line | Count | Source | 127 | 36.4k | fn visit_type_id(&mut self, resolve: &Resolve, ty: TypeId) { | 128 | 36.4k | if self.before_visit_type_id(ty) { | 129 | 29.7k | self.visit_type_def(resolve, &resolve.types[ty]); | 130 | 29.7k | self.after_visit_type_id(ty); | 131 | 29.7k | } | 132 | 36.4k | } |
|
133 | | |
134 | 42.2k | fn visit_type_def(&mut self, resolve: &Resolve, ty: &TypeDef) { |
135 | 983 | match &ty.kind { |
136 | 952 | TypeDefKind::Type(t) |
137 | 1.16k | | TypeDefKind::List(t) |
138 | 491 | | TypeDefKind::FixedLengthList(t, ..) |
139 | 5.46k | | TypeDefKind::Option(t) |
140 | 881 | | TypeDefKind::Future(Some(t)) |
141 | 9.52k | | TypeDefKind::Stream(Some(t)) => self.visit_type(resolve, t), |
142 | 0 | TypeDefKind::Map(k, v) => { |
143 | 0 | self.visit_type(resolve, k); |
144 | 0 | self.visit_type(resolve, v); |
145 | 0 | } |
146 | 830 | TypeDefKind::Handle(handle) => match handle { |
147 | 264 | crate::Handle::Own(ty) => self.visit_type_id(resolve, *ty), |
148 | 566 | crate::Handle::Borrow(ty) => self.visit_type_id(resolve, *ty), |
149 | | }, |
150 | 1.44k | TypeDefKind::Resource => {} |
151 | 916 | TypeDefKind::Record(r) => { |
152 | 2.58k | for field in r.fields.iter() { |
153 | 2.58k | self.visit_type(resolve, &field.ty); |
154 | 2.58k | } |
155 | | } |
156 | 8.75k | TypeDefKind::Tuple(r) => { |
157 | 32.0k | for ty in r.types.iter() { |
158 | 32.0k | self.visit_type(resolve, ty); |
159 | 32.0k | } |
160 | | } |
161 | 668 | TypeDefKind::Variant(v) => { |
162 | 3.68k | for case in v.cases.iter() { |
163 | 3.68k | if let Some(ty) = &case.ty { |
164 | 3.48k | self.visit_type(resolve, ty); |
165 | 3.48k | } |
166 | | } |
167 | | } |
168 | 4.13k | TypeDefKind::Result(r) => { |
169 | 4.13k | if let Some(ty) = &r.ok { |
170 | 3.84k | self.visit_type(resolve, ty); |
171 | 3.84k | } |
172 | 4.13k | if let Some(ty) = &r.err { |
173 | 3.65k | self.visit_type(resolve, ty); |
174 | 3.65k | } |
175 | | } |
176 | | TypeDefKind::Flags(_) |
177 | | | TypeDefKind::Enum(_) |
178 | | | TypeDefKind::Future(None) |
179 | 16.0k | | TypeDefKind::Stream(None) => {} |
180 | 0 | TypeDefKind::Unknown => unreachable!(), |
181 | | } |
182 | 42.2k | } <<wit_parser::resolve::Resolve>::assert_world_imports_type_deps::MyVisit as wit_parser::live::TypeIdVisitor>::visit_type_def Line | Count | Source | 134 | 12.5k | fn visit_type_def(&mut self, resolve: &Resolve, ty: &TypeDef) { | 135 | 190 | match &ty.kind { | 136 | 302 | TypeDefKind::Type(t) | 137 | 596 | | TypeDefKind::List(t) | 138 | 188 | | TypeDefKind::FixedLengthList(t, ..) | 139 | 3.54k | | TypeDefKind::Option(t) | 140 | 162 | | TypeDefKind::Future(Some(t)) | 141 | 5.15k | | TypeDefKind::Stream(Some(t)) => self.visit_type(resolve, t), | 142 | 0 | TypeDefKind::Map(k, v) => { | 143 | 0 | self.visit_type(resolve, k); | 144 | 0 | self.visit_type(resolve, v); | 145 | 0 | } | 146 | 330 | TypeDefKind::Handle(handle) => match handle { | 147 | 94 | crate::Handle::Own(ty) => self.visit_type_id(resolve, *ty), | 148 | 236 | crate::Handle::Borrow(ty) => self.visit_type_id(resolve, *ty), | 149 | | }, | 150 | 604 | TypeDefKind::Resource => {} | 151 | 250 | TypeDefKind::Record(r) => { | 152 | 524 | for field in r.fields.iter() { | 153 | 524 | self.visit_type(resolve, &field.ty); | 154 | 524 | } | 155 | | } | 156 | 3.72k | TypeDefKind::Tuple(r) => { | 157 | 15.0k | for ty in r.types.iter() { | 158 | 15.0k | self.visit_type(resolve, ty); | 159 | 15.0k | } | 160 | | } | 161 | 156 | TypeDefKind::Variant(v) => { | 162 | 412 | for case in v.cases.iter() { | 163 | 412 | if let Some(ty) = &case.ty { | 164 | 310 | self.visit_type(resolve, ty); | 165 | 310 | } | 166 | | } | 167 | | } | 168 | 628 | TypeDefKind::Result(r) => { | 169 | 628 | if let Some(ty) = &r.ok { | 170 | 502 | self.visit_type(resolve, ty); | 171 | 502 | } | 172 | 628 | if let Some(ty) = &r.err { | 173 | 452 | self.visit_type(resolve, ty); | 174 | 452 | } | 175 | | } | 176 | | TypeDefKind::Flags(_) | 177 | | | TypeDefKind::Enum(_) | 178 | | | TypeDefKind::Future(None) | 179 | 1.74k | | TypeDefKind::Stream(None) => {} | 180 | 0 | TypeDefKind::Unknown => unreachable!(), | 181 | | } | 182 | 12.5k | } |
<wit_parser::live::LiveTypes as wit_parser::live::TypeIdVisitor>::visit_type_def Line | Count | Source | 134 | 29.7k | fn visit_type_def(&mut self, resolve: &Resolve, ty: &TypeDef) { | 135 | 793 | match &ty.kind { | 136 | 650 | TypeDefKind::Type(t) | 137 | 569 | | TypeDefKind::List(t) | 138 | 303 | | TypeDefKind::FixedLengthList(t, ..) | 139 | 1.91k | | TypeDefKind::Option(t) | 140 | 719 | | TypeDefKind::Future(Some(t)) | 141 | 4.37k | | TypeDefKind::Stream(Some(t)) => self.visit_type(resolve, t), | 142 | 0 | TypeDefKind::Map(k, v) => { | 143 | 0 | self.visit_type(resolve, k); | 144 | 0 | self.visit_type(resolve, v); | 145 | 0 | } | 146 | 500 | TypeDefKind::Handle(handle) => match handle { | 147 | 170 | crate::Handle::Own(ty) => self.visit_type_id(resolve, *ty), | 148 | 330 | crate::Handle::Borrow(ty) => self.visit_type_id(resolve, *ty), | 149 | | }, | 150 | 839 | TypeDefKind::Resource => {} | 151 | 666 | TypeDefKind::Record(r) => { | 152 | 2.06k | for field in r.fields.iter() { | 153 | 2.06k | self.visit_type(resolve, &field.ty); | 154 | 2.06k | } | 155 | | } | 156 | 5.03k | TypeDefKind::Tuple(r) => { | 157 | 17.0k | for ty in r.types.iter() { | 158 | 17.0k | self.visit_type(resolve, ty); | 159 | 17.0k | } | 160 | | } | 161 | 512 | TypeDefKind::Variant(v) => { | 162 | 3.27k | for case in v.cases.iter() { | 163 | 3.27k | if let Some(ty) = &case.ty { | 164 | 3.17k | self.visit_type(resolve, ty); | 165 | 3.17k | } | 166 | | } | 167 | | } | 168 | 3.50k | TypeDefKind::Result(r) => { | 169 | 3.50k | if let Some(ty) = &r.ok { | 170 | 3.34k | self.visit_type(resolve, ty); | 171 | 3.34k | } | 172 | 3.50k | if let Some(ty) = &r.err { | 173 | 3.19k | self.visit_type(resolve, ty); | 174 | 3.19k | } | 175 | | } | 176 | | TypeDefKind::Flags(_) | 177 | | | TypeDefKind::Enum(_) | 178 | | | TypeDefKind::Future(None) | 179 | 14.2k | | TypeDefKind::Stream(None) => {} | 180 | 0 | TypeDefKind::Unknown => unreachable!(), | 181 | | } | 182 | 29.7k | } |
|
183 | | |
184 | 76.4k | fn visit_type(&mut self, resolve: &Resolve, ty: &Type) { |
185 | 76.4k | match ty { |
186 | 25.1k | Type::Id(id) => self.visit_type_id(resolve, *id), |
187 | 51.2k | _ => {} |
188 | | } |
189 | 76.4k | } <<wit_parser::resolve::Resolve>::assert_world_imports_type_deps::MyVisit as wit_parser::live::TypeIdVisitor>::visit_type Line | Count | Source | 184 | 22.0k | fn visit_type(&mut self, resolve: &Resolve, ty: &Type) { | 185 | 22.0k | match ty { | 186 | 8.64k | Type::Id(id) => self.visit_type_id(resolve, *id), | 187 | 13.3k | _ => {} | 188 | | } | 189 | 22.0k | } |
<wit_parser::live::LiveTypes as wit_parser::live::TypeIdVisitor>::visit_type Line | Count | Source | 184 | 54.4k | fn visit_type(&mut self, resolve: &Resolve, ty: &Type) { | 185 | 54.4k | match ty { | 186 | 16.5k | Type::Id(id) => self.visit_type_id(resolve, *id), | 187 | 37.9k | _ => {} | 188 | | } | 189 | 54.4k | } |
|
190 | | } |
191 | | |
192 | | #[cfg(test)] |
193 | | mod tests { |
194 | | use super::{LiveTypes, Resolve}; |
195 | | use alloc::string::String; |
196 | | use alloc::vec::Vec; |
197 | | |
198 | | fn live(wit: &str, ty: &str) -> Vec<String> { |
199 | | let mut resolve = Resolve::default(); |
200 | | resolve.push_str("test.wit", wit).unwrap(); |
201 | | let (_, interface) = resolve.interfaces.iter().next_back().unwrap(); |
202 | | let ty = interface.types[ty]; |
203 | | let mut live = LiveTypes::default(); |
204 | | live.add_type_id(&resolve, ty); |
205 | | |
206 | | live.iter() |
207 | | .filter_map(|ty| resolve.types[ty].name.clone()) |
208 | | .collect() |
209 | | } |
210 | | |
211 | | #[test] |
212 | | fn no_deps() { |
213 | | let types = live( |
214 | | " |
215 | | package foo:bar; |
216 | | |
217 | | interface foo { |
218 | | type t = u32; |
219 | | } |
220 | | ", |
221 | | "t", |
222 | | ); |
223 | | assert_eq!(types, ["t"]); |
224 | | } |
225 | | |
226 | | #[test] |
227 | | fn one_dep() { |
228 | | let types = live( |
229 | | " |
230 | | package foo:bar; |
231 | | |
232 | | interface foo { |
233 | | type t = u32; |
234 | | type u = t; |
235 | | } |
236 | | ", |
237 | | "u", |
238 | | ); |
239 | | assert_eq!(types, ["t", "u"]); |
240 | | } |
241 | | |
242 | | #[test] |
243 | | fn chain() { |
244 | | let types = live( |
245 | | " |
246 | | package foo:bar; |
247 | | |
248 | | interface foo { |
249 | | resource t1; |
250 | | record t2 { |
251 | | x: t1, |
252 | | } |
253 | | variant t3 { |
254 | | x(t2), |
255 | | } |
256 | | flags t4 { a } |
257 | | enum t5 { a } |
258 | | type t6 = tuple<t5, t4, t3>; |
259 | | } |
260 | | ", |
261 | | "t6", |
262 | | ); |
263 | | assert_eq!(types, ["t5", "t4", "t1", "t2", "t3", "t6"]); |
264 | | } |
265 | | } |