1 use std::collections::HashMap; 2 use wit_parser::*; 3 4 #[derive(Default)] 5 pub struct Types { 6 type_info: HashMap<TypeId, TypeInfo>, 7 } 8 9 #[derive(Default, Clone, Copy, Debug, PartialEq)] 10 pub struct TypeInfo { 11 /// Whether or not this type is ever used (transitively) within a borrowed 12 /// context, or a parameter to an export function. 13 pub borrowed: bool, 14 15 /// Whether or not this type is ever used (transitively) within an owned 16 /// context, such as the result of an exported function or in the params or 17 /// results of an imported function. 18 pub owned: bool, 19 20 /// Whether or not this type is ever used (transitively) within the 21 /// error case in the result of a function. 22 pub error: bool, 23 24 /// Whether or not this type (transitively) has a list. 25 pub has_list: bool, 26 27 /// Whether or not this type (transitively) has a handle. 28 pub has_handle: bool, 29 30 /// Whether or not this type (transitively) has a future or a stream. 31 pub has_future_or_stream: bool, 32 } 33 34 impl std::ops::BitOrAssign for TypeInfo { bitor_assign(&mut self, rhs: Self)35 fn bitor_assign(&mut self, rhs: Self) { 36 self.borrowed |= rhs.borrowed; 37 self.owned |= rhs.owned; 38 self.error |= rhs.error; 39 self.has_list |= rhs.has_list; 40 self.has_handle |= rhs.has_handle; 41 self.has_future_or_stream |= rhs.has_future_or_stream; 42 } 43 } 44 45 impl Types { analyze(&mut self, resolve: &Resolve, world: WorldId)46 pub fn analyze(&mut self, resolve: &Resolve, world: WorldId) { 47 // Build up all type information first which is inherited through types, 48 // such as properties of borrows/lists/etc. 49 for (t, _) in resolve.types.iter() { 50 self.type_id_info(resolve, t); 51 } 52 53 // ... next handle borrowed/owned flags which aren't inherited through 54 // types. 55 let world = &resolve.worlds[world]; 56 for (import, (_, item)) in world 57 .imports 58 .iter() 59 .map(|i| (true, i)) 60 .chain(world.exports.iter().map(|i| (false, i))) 61 { 62 match item { 63 WorldItem::Function(f) => self.type_info_func(resolve, f, import), 64 WorldItem::Interface { id, .. } => { 65 let iface = &resolve.interfaces[*id]; 66 67 for (_, t) in iface.types.iter() { 68 self.type_id_info(resolve, *t); 69 } 70 for (_, f) in iface.functions.iter() { 71 self.type_info_func(resolve, f, import); 72 } 73 } 74 WorldItem::Type { id, .. } => { 75 self.type_id_info(resolve, *id); 76 } 77 } 78 } 79 } 80 type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool)81 fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) { 82 let mut live = LiveTypes::default(); 83 for param in func.params.iter() { 84 self.type_info(resolve, ¶m.ty); 85 live.add_type(resolve, ¶m.ty); 86 } 87 for id in live.iter() { 88 if resolve.types[id].name.is_some() { 89 let info = self.type_info.get_mut(&id).unwrap(); 90 if import { 91 info.owned = true; 92 } else { 93 info.borrowed = true; 94 } 95 } 96 } 97 let mut live = LiveTypes::default(); 98 if let Some(ty) = &func.result { 99 self.type_info(resolve, ty); 100 live.add_type(resolve, ty); 101 } 102 for id in live.iter() { 103 if resolve.types[id].name.is_some() { 104 self.type_info.get_mut(&id).unwrap().owned = true; 105 } 106 } 107 108 if let Some(Type::Id(id)) = func.result { 109 if let TypeDefKind::Result(Result_ { 110 err: Some(Type::Id(id)), 111 .. 112 }) = &resolve.types[id].kind 113 { 114 let id = super::resolve_type_definition_id(resolve, *id); 115 self.type_info.get_mut(&id).unwrap().error = true; 116 } 117 } 118 } 119 get(&self, id: TypeId) -> TypeInfo120 pub fn get(&self, id: TypeId) -> TypeInfo { 121 self.type_info[&id] 122 } 123 type_id_info(&mut self, resolve: &Resolve, ty: TypeId) -> TypeInfo124 fn type_id_info(&mut self, resolve: &Resolve, ty: TypeId) -> TypeInfo { 125 if let Some(info) = self.type_info.get(&ty) { 126 return *info; 127 } 128 let mut info = TypeInfo::default(); 129 match &resolve.types[ty].kind { 130 TypeDefKind::Record(r) => { 131 for field in r.fields.iter() { 132 info |= self.type_info(resolve, &field.ty); 133 } 134 } 135 TypeDefKind::Tuple(t) => { 136 for ty in t.types.iter() { 137 info |= self.type_info(resolve, ty); 138 } 139 } 140 TypeDefKind::Flags(_) => {} 141 TypeDefKind::Enum(_) => {} 142 TypeDefKind::Variant(v) => { 143 for case in v.cases.iter() { 144 info |= self.optional_type_info(resolve, case.ty.as_ref()); 145 } 146 } 147 TypeDefKind::List(ty) => { 148 info = self.type_info(resolve, ty); 149 info.has_list = true; 150 } 151 TypeDefKind::Map(k, v) => { 152 info = self.type_info(resolve, k); 153 info |= self.type_info(resolve, v); 154 info.has_list = true; 155 } 156 TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => { 157 info = self.type_info(resolve, ty); 158 } 159 TypeDefKind::Result(r) => { 160 info = self.optional_type_info(resolve, r.ok.as_ref()); 161 info |= self.optional_type_info(resolve, r.err.as_ref()); 162 } 163 TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => { 164 info = self.optional_type_info(resolve, ty.as_ref()); 165 info.has_future_or_stream = true; 166 } 167 TypeDefKind::Handle(_) => info.has_handle = true, 168 TypeDefKind::Resource => {} 169 TypeDefKind::Unknown => unreachable!(), 170 TypeDefKind::FixedLengthList(..) => todo!(), 171 } 172 self.type_info.insert(ty, info); 173 info 174 } 175 type_info(&mut self, resolve: &Resolve, ty: &Type) -> TypeInfo176 fn type_info(&mut self, resolve: &Resolve, ty: &Type) -> TypeInfo { 177 let mut info = TypeInfo::default(); 178 match ty { 179 Type::String => info.has_list = true, 180 Type::Id(id) => return self.type_id_info(resolve, *id), 181 _ => {} 182 } 183 info 184 } 185 optional_type_info(&mut self, resolve: &Resolve, ty: Option<&Type>) -> TypeInfo186 fn optional_type_info(&mut self, resolve: &Resolve, ty: Option<&Type>) -> TypeInfo { 187 match ty { 188 Some(ty) => self.type_info(resolve, ty), 189 None => TypeInfo::default(), 190 } 191 } 192 } 193 194 impl TypeInfo { is_copy(&self) -> bool195 pub fn is_copy(&self) -> bool { 196 !self.has_list && !self.has_handle && !self.has_future_or_stream 197 } 198 is_clone(&self) -> bool199 pub fn is_clone(&self) -> bool { 200 !self.has_handle && !self.has_future_or_stream 201 } 202 } 203