wasmtime_wit_bindgen/
types.rs1use std::collections::HashMap;
2use wit_parser::*;
3
4#[derive(Default)]
5pub struct Types {
6 type_info: HashMap<TypeId, TypeInfo>,
7}
8
9#[derive(Default, Clone, Copy, Debug, PartialEq)]
10pub struct TypeInfo {
11 pub borrowed: bool,
14
15 pub owned: bool,
19
20 pub error: bool,
23
24 pub has_list: bool,
26
27 pub has_handle: bool,
29}
30
31impl std::ops::BitOrAssign for TypeInfo {
32 fn bitor_assign(&mut self, rhs: Self) {
33 self.borrowed |= rhs.borrowed;
34 self.owned |= rhs.owned;
35 self.error |= rhs.error;
36 self.has_list |= rhs.has_list;
37 self.has_handle |= rhs.has_handle;
38 }
39}
40
41impl Types {
42 pub fn analyze(&mut self, resolve: &Resolve, world: WorldId) {
43 for (t, _) in resolve.types.iter() {
46 self.type_id_info(resolve, t);
47 }
48
49 let world = &resolve.worlds[world];
52 for (import, (_, item)) in world
53 .imports
54 .iter()
55 .map(|i| (true, i))
56 .chain(world.exports.iter().map(|i| (false, i)))
57 {
58 match item {
59 WorldItem::Function(f) => self.type_info_func(resolve, f, import),
60 WorldItem::Interface { id, .. } => {
61 let iface = &resolve.interfaces[*id];
62
63 for (_, t) in iface.types.iter() {
64 self.type_id_info(resolve, *t);
65 }
66 for (_, f) in iface.functions.iter() {
67 self.type_info_func(resolve, f, import);
68 }
69 }
70 WorldItem::Type(id) => {
71 self.type_id_info(resolve, *id);
72 }
73 }
74 }
75 }
76
77 fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) {
78 let mut live = LiveTypes::default();
79 for (_, ty) in func.params.iter() {
80 self.type_info(resolve, ty);
81 live.add_type(resolve, ty);
82 }
83 for id in live.iter() {
84 if resolve.types[id].name.is_some() {
85 let info = self.type_info.get_mut(&id).unwrap();
86 if import {
87 info.owned = true;
88 } else {
89 info.borrowed = true;
90 }
91 }
92 }
93 let mut live = LiveTypes::default();
94 if let Some(ty) = &func.result {
95 self.type_info(resolve, ty);
96 live.add_type(resolve, ty);
97 }
98 for id in live.iter() {
99 if resolve.types[id].name.is_some() {
100 self.type_info.get_mut(&id).unwrap().owned = true;
101 }
102 }
103
104 if let Some(Type::Id(id)) = func.result {
105 if let TypeDefKind::Result(Result_ {
106 err: Some(Type::Id(id)),
107 ..
108 }) = &resolve.types[id].kind
109 {
110 let id = super::resolve_type_definition_id(resolve, *id);
111 self.type_info.get_mut(&id).unwrap().error = true;
112 }
113 }
114 }
115
116 pub fn get(&self, id: TypeId) -> TypeInfo {
117 self.type_info[&id]
118 }
119
120 fn type_id_info(&mut self, resolve: &Resolve, ty: TypeId) -> TypeInfo {
121 if let Some(info) = self.type_info.get(&ty) {
122 return *info;
123 }
124 let mut info = TypeInfo::default();
125 match &resolve.types[ty].kind {
126 TypeDefKind::Record(r) => {
127 for field in r.fields.iter() {
128 info |= self.type_info(resolve, &field.ty);
129 }
130 }
131 TypeDefKind::Tuple(t) => {
132 for ty in t.types.iter() {
133 info |= self.type_info(resolve, ty);
134 }
135 }
136 TypeDefKind::Flags(_) => {}
137 TypeDefKind::Enum(_) => {}
138 TypeDefKind::Variant(v) => {
139 for case in v.cases.iter() {
140 info |= self.optional_type_info(resolve, case.ty.as_ref());
141 }
142 }
143 TypeDefKind::List(ty) => {
144 info = self.type_info(resolve, ty);
145 info.has_list = true;
146 }
147 TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => {
148 info = self.type_info(resolve, ty);
149 }
150 TypeDefKind::Result(r) => {
151 info = self.optional_type_info(resolve, r.ok.as_ref());
152 info |= self.optional_type_info(resolve, r.err.as_ref());
153 }
154 TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
155 info = self.optional_type_info(resolve, ty.as_ref());
156 }
157 TypeDefKind::Handle(_) => info.has_handle = true,
158 TypeDefKind::Resource => {}
159 TypeDefKind::Unknown => unreachable!(),
160 }
161 self.type_info.insert(ty, info);
162 info
163 }
164
165 fn type_info(&mut self, resolve: &Resolve, ty: &Type) -> TypeInfo {
166 let mut info = TypeInfo::default();
167 match ty {
168 Type::String => info.has_list = true,
169 Type::Id(id) => return self.type_id_info(resolve, *id),
170 _ => {}
171 }
172 info
173 }
174
175 fn optional_type_info(&mut self, resolve: &Resolve, ty: Option<&Type>) -> TypeInfo {
176 match ty {
177 Some(ty) => self.type_info(resolve, ty),
178 None => TypeInfo::default(),
179 }
180 }
181}
182
183impl TypeInfo {
184 pub fn is_copy(&self) -> bool {
185 !self.has_list && !self.has_handle
186 }
187
188 pub fn is_clone(&self) -> bool {
189 !self.has_handle
190 }
191}