| 1 | //! Types relating to type information provided by validation. | 
| 2 |  | 
|---|
| 3 | use super::core::Module; | 
|---|
| 4 | #[ cfg(feature = "component-model")] | 
|---|
| 5 | use crate::validator::component::ComponentState; | 
|---|
| 6 | #[ cfg(feature = "component-model")] | 
|---|
| 7 | use crate::validator::component_types::{ComponentTypeAlloc, ComponentTypeList}; | 
|---|
| 8 | use crate::{collections::map::Entry, AbstractHeapType}; | 
|---|
| 9 | use crate::{prelude::*, CompositeInnerType}; | 
|---|
| 10 | use crate::{ | 
|---|
| 11 | Export, ExternalKind, GlobalType, Import, Matches, MemoryType, PackedIndex, RecGroup, RefType, | 
|---|
| 12 | Result, SubType, TableType, TypeRef, UnpackedIndex, ValType, WithRecGroup, | 
|---|
| 13 | }; | 
|---|
| 14 | use crate::{FuncType, HeapType, ValidatorId}; | 
|---|
| 15 | use alloc::sync::Arc; | 
|---|
| 16 | use core::ops::{Deref, DerefMut, Index, Range}; | 
|---|
| 17 | use core::{hash::Hash, mem}; | 
|---|
| 18 |  | 
|---|
| 19 | /// A trait shared by all type identifiers. | 
|---|
| 20 | /// | 
|---|
| 21 | /// Any id that can be used to get a type from a `Types`. | 
|---|
| 22 | // | 
|---|
| 23 | // Or, internally, from a `TypeList`. | 
|---|
| 24 | pub trait TypeIdentifier: core::fmt::Debug + Copy + Eq + Sized + 'static { | 
|---|
| 25 | /// The data pointed to by this type of id. | 
|---|
| 26 | type Data: TypeData<Id = Self>; | 
|---|
| 27 |  | 
|---|
| 28 | /// Create a type id from an index. | 
|---|
| 29 | #[ doc(hidden)] | 
|---|
| 30 | fn from_index(index: u32) -> Self; | 
|---|
| 31 |  | 
|---|
| 32 | /// Get a shared reference to the list where this id's type data is stored | 
|---|
| 33 | /// within. | 
|---|
| 34 | #[ doc(hidden)] | 
|---|
| 35 | fn list(types: &TypeList) -> &SnapshotList<Self::Data>; | 
|---|
| 36 |  | 
|---|
| 37 | /// Get an exclusive reference to the list where this id's type data is | 
|---|
| 38 | /// stored within. | 
|---|
| 39 | #[ doc(hidden)] | 
|---|
| 40 | fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data>; | 
|---|
| 41 |  | 
|---|
| 42 | /// The raw index of this id. | 
|---|
| 43 | #[ doc(hidden)] | 
|---|
| 44 | fn index(&self) -> usize; | 
|---|
| 45 | } | 
|---|
| 46 |  | 
|---|
| 47 | /// A trait shared by all types within a `Types`. | 
|---|
| 48 | /// | 
|---|
| 49 | /// This is the data that can be retreived by indexing with the associated | 
|---|
| 50 | /// [`TypeIdentifier`]. | 
|---|
| 51 | pub trait TypeData: core::fmt::Debug { | 
|---|
| 52 | /// The identifier for this type data. | 
|---|
| 53 | type Id: TypeIdentifier<Data = Self>; | 
|---|
| 54 |  | 
|---|
| 55 | /// Get the info for this type. | 
|---|
| 56 | #[ doc(hidden)] | 
|---|
| 57 | fn type_info(&self, types: &TypeList) -> TypeInfo; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | macro_rules! define_type_id { | 
|---|
| 61 | ($name:ident, $data:ty, $($list:ident).*, $type_str:expr) => { | 
|---|
| 62 | #[doc = "Represents a unique identifier for a "] | 
|---|
| 63 | #[doc = $type_str] | 
|---|
| 64 | #[doc = " type known to a [`crate::Validator`]."] | 
|---|
| 65 | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 
|---|
| 66 | #[repr(C)] // Use fixed field layout to ensure minimal size. | 
|---|
| 67 | pub struct $name { | 
|---|
| 68 | /// The index into the associated list of types. | 
|---|
| 69 | index: u32, | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 | impl TypeIdentifier for $name { | 
|---|
| 73 | type Data = $data; | 
|---|
| 74 |  | 
|---|
| 75 | fn from_index(index: u32) -> Self { | 
|---|
| 76 | $name { index } | 
|---|
| 77 | } | 
|---|
| 78 |  | 
|---|
| 79 | fn list(types: &TypeList) -> &SnapshotList<Self::Data> { | 
|---|
| 80 | &types.$($list).* | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> { | 
|---|
| 84 | &mut types.$($list).* | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 | fn index(&self) -> usize { | 
|---|
| 88 | usize::try_from(self.index).unwrap() | 
|---|
| 89 | } | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 |  | 
|---|
| 93 | // The size of type IDs was seen to have a large-ish impact in #844, so | 
|---|
| 94 | // this assert ensures that it stays relatively small. | 
|---|
| 95 | const _: () = { | 
|---|
| 96 | assert!(core::mem::size_of::<$name>() <= 4); | 
|---|
| 97 | }; | 
|---|
| 98 | }; | 
|---|
| 99 | } | 
|---|
| 100 | pub(crate) use define_type_id; | 
|---|
| 101 |  | 
|---|
| 102 | /// Represents a unique identifier for a core type type known to a | 
|---|
| 103 | /// [`crate::Validator`]. | 
|---|
| 104 | #[ derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 
|---|
| 105 | #[ repr(C)] | 
|---|
| 106 | pub struct CoreTypeId { | 
|---|
| 107 | index: u32, | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 | #[ test] | 
|---|
| 111 | fn assert_core_type_id_small() { | 
|---|
| 112 | assert!(core::mem::size_of::<CoreTypeId>() <= 4); | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | impl TypeIdentifier for CoreTypeId { | 
|---|
| 116 | type Data = SubType; | 
|---|
| 117 |  | 
|---|
| 118 | fn from_index(index: u32) -> Self { | 
|---|
| 119 | CoreTypeId { index } | 
|---|
| 120 | } | 
|---|
| 121 |  | 
|---|
| 122 | fn list(types: &TypeList) -> &SnapshotList<Self::Data> { | 
|---|
| 123 | &types.core_types | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> { | 
|---|
| 127 | &mut types.core_types | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | fn index(&self) -> usize { | 
|---|
| 131 | usize::try_from(self.index).unwrap() | 
|---|
| 132 | } | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | impl TypeData for SubType { | 
|---|
| 136 | type Id = CoreTypeId; | 
|---|
| 137 |  | 
|---|
| 138 | fn type_info(&self, _types: &TypeList) -> TypeInfo { | 
|---|
| 139 | // TODO(#1036): calculate actual size for func, array, struct. | 
|---|
| 140 | let size: u32 = 1 + match &self.composite_type.inner { | 
|---|
| 141 | CompositeInnerType::Func(ty: &FuncType) => 1 + (ty.params().len() + ty.results().len()) as u32, | 
|---|
| 142 | CompositeInnerType::Array(_) => 2, | 
|---|
| 143 | CompositeInnerType::Struct(ty: &StructType) => 1 + 2 * ty.fields.len() as u32, | 
|---|
| 144 | CompositeInnerType::Cont(_) => 1, | 
|---|
| 145 | }; | 
|---|
| 146 | TypeInfo::core(size) | 
|---|
| 147 | } | 
|---|
| 148 | } | 
|---|
| 149 |  | 
|---|
| 150 | define_type_id!( | 
|---|
| 151 | RecGroupId, | 
|---|
| 152 | Range<CoreTypeId>, | 
|---|
| 153 | rec_group_elements, | 
|---|
| 154 | "recursion group" | 
|---|
| 155 | ); | 
|---|
| 156 |  | 
|---|
| 157 | impl TypeData for Range<CoreTypeId> { | 
|---|
| 158 | type Id = RecGroupId; | 
|---|
| 159 |  | 
|---|
| 160 | fn type_info(&self, _types: &TypeList) -> TypeInfo { | 
|---|
| 161 | let size: usize = self.end.index() - self.start.index(); | 
|---|
| 162 | TypeInfo::core(size:u32::try_from(size).unwrap()) | 
|---|
| 163 | } | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | /// Metadata about a type and its transitive structure. | 
|---|
| 167 | /// | 
|---|
| 168 | /// Currently contains two properties: | 
|---|
| 169 | /// | 
|---|
| 170 | /// * The "size" of a type - a proxy to the recursive size of a type if | 
|---|
| 171 | ///   everything in the type were unique (e.g. no shared references). Not an | 
|---|
| 172 | ///   approximation of runtime size, but instead of type-complexity size if | 
|---|
| 173 | ///   someone were to visit each element of the type individually. For example | 
|---|
| 174 | ///   `u32` has size 1 and `(list u32)` has size 2 (roughly). Used to prevent | 
|---|
| 175 | ///   massive trees of types. | 
|---|
| 176 | /// | 
|---|
| 177 | /// * Whether or not a type contains a "borrow" transitively inside of it. For | 
|---|
| 178 | ///   example `(borrow $t)` and `(list (borrow $t))` both contain borrows, but | 
|---|
| 179 | ///   `(list u32)` does not. Used to validate that component function results do | 
|---|
| 180 | ///   not contain borrows. | 
|---|
| 181 | /// | 
|---|
| 182 | /// Currently this is represented as a compact 32-bit integer to ensure that | 
|---|
| 183 | /// `TypeId`, which this is stored in, remains relatively small. The maximum | 
|---|
| 184 | /// type size allowed in wasmparser is 1M at this time which is 20 bits of | 
|---|
| 185 | /// information, and then one more bit is used for whether or not a borrow is | 
|---|
| 186 | /// used. Currently this uses the low 24 bits for the type size and the MSB for | 
|---|
| 187 | /// the borrow bit. | 
|---|
| 188 | #[ derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 
|---|
| 189 | // Only public because it shows up in a public trait's `doc(hidden)` method. | 
|---|
| 190 | #[ doc(hidden)] | 
|---|
| 191 | pub struct TypeInfo(u32); | 
|---|
| 192 |  | 
|---|
| 193 | impl TypeInfo { | 
|---|
| 194 | /// Creates a new blank set of type information. | 
|---|
| 195 | /// | 
|---|
| 196 | /// Defaults to size 1 to ensure that this consumes space in the final type | 
|---|
| 197 | /// structure. | 
|---|
| 198 | pub(crate) fn new() -> TypeInfo { | 
|---|
| 199 | TypeInfo::_new(1, false) | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | /// Creates a new blank set of information about a leaf "borrow" type which | 
|---|
| 203 | /// has size 1. | 
|---|
| 204 | #[ cfg(feature = "component-model")] | 
|---|
| 205 | pub(crate) fn borrow() -> TypeInfo { | 
|---|
| 206 | TypeInfo::_new(1, true) | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | /// Creates type information corresponding to a core type of the `size` | 
|---|
| 210 | /// specified, meaning no borrows are contained within. | 
|---|
| 211 | pub(crate) fn core(size: u32) -> TypeInfo { | 
|---|
| 212 | TypeInfo::_new(size, false) | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | fn _new(size: u32, contains_borrow: bool) -> TypeInfo { | 
|---|
| 216 | assert!(size < (1 << 24)); | 
|---|
| 217 | TypeInfo(size | ((contains_borrow as u32) << 31)) | 
|---|
| 218 | } | 
|---|
| 219 |  | 
|---|
| 220 | /// Combines another set of type information into this one, for example if | 
|---|
| 221 | /// this is a record which has `other` as a field. | 
|---|
| 222 | /// | 
|---|
| 223 | /// Updates the size of `self` and whether or not this type contains a | 
|---|
| 224 | /// borrow based on whether `other` contains a borrow. | 
|---|
| 225 | /// | 
|---|
| 226 | /// Returns an error if the type size would exceed this crate's static limit | 
|---|
| 227 | /// of a type size. | 
|---|
| 228 | #[ cfg(feature = "component-model")] | 
|---|
| 229 | pub(crate) fn combine(&mut self, other: TypeInfo, offset: usize) -> Result<()> { | 
|---|
| 230 | *self = TypeInfo::_new( | 
|---|
| 231 | super::combine_type_sizes(self.size(), other.size(), offset)?, | 
|---|
| 232 | self.contains_borrow() || other.contains_borrow(), | 
|---|
| 233 | ); | 
|---|
| 234 | Ok(()) | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | pub(crate) fn size(&self) -> u32 { | 
|---|
| 238 | self.0 & 0xffffff | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | #[ cfg(feature = "component-model")] | 
|---|
| 242 | pub(crate) fn contains_borrow(&self) -> bool { | 
|---|
| 243 | (self.0 >> 31) != 0 | 
|---|
| 244 | } | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | /// The entity type for imports and exports of a module. | 
|---|
| 248 | #[ derive(Debug, Clone, Copy)] | 
|---|
| 249 | pub enum EntityType { | 
|---|
| 250 | /// The entity is a function. | 
|---|
| 251 | Func(CoreTypeId), | 
|---|
| 252 | /// The entity is a table. | 
|---|
| 253 | Table(TableType), | 
|---|
| 254 | /// The entity is a memory. | 
|---|
| 255 | Memory(MemoryType), | 
|---|
| 256 | /// The entity is a global. | 
|---|
| 257 | Global(GlobalType), | 
|---|
| 258 | /// The entity is a tag. | 
|---|
| 259 | Tag(CoreTypeId), | 
|---|
| 260 | } | 
|---|
| 261 |  | 
|---|
| 262 | impl EntityType { | 
|---|
| 263 | #[ cfg(feature = "component-model")] | 
|---|
| 264 | pub(crate) fn desc(&self) -> &'static str { | 
|---|
| 265 | match self { | 
|---|
| 266 | Self::Func(_) => "func", | 
|---|
| 267 | Self::Table(_) => "table", | 
|---|
| 268 | Self::Memory(_) => "memory", | 
|---|
| 269 | Self::Global(_) => "global", | 
|---|
| 270 | Self::Tag(_) => "tag", | 
|---|
| 271 | } | 
|---|
| 272 | } | 
|---|
| 273 |  | 
|---|
| 274 | pub(crate) fn info(&self, types: &TypeList) -> TypeInfo { | 
|---|
| 275 | match self { | 
|---|
| 276 | Self::Func(id: &CoreTypeId) | Self::Tag(id: &CoreTypeId) => types[*id].type_info(types), | 
|---|
| 277 | Self::Table(_) | Self::Memory(_) | Self::Global(_) => TypeInfo::new(), | 
|---|
| 278 | } | 
|---|
| 279 | } | 
|---|
| 280 | } | 
|---|
| 281 |  | 
|---|
| 282 | #[ allow(clippy::large_enum_variant)] | 
|---|
| 283 | pub(super) enum TypesKind { | 
|---|
| 284 | Module(Arc<Module>), | 
|---|
| 285 | #[ cfg(feature = "component-model")] | 
|---|
| 286 | Component(ComponentState), | 
|---|
| 287 | } | 
|---|
| 288 |  | 
|---|
| 289 | /// Represents the types known to a [`crate::Validator`] once validation has completed. | 
|---|
| 290 | /// | 
|---|
| 291 | /// The type information is returned via the [`crate::Validator::end`] method. | 
|---|
| 292 | pub struct Types { | 
|---|
| 293 | id: ValidatorId, | 
|---|
| 294 | pub(super) list: TypeList, | 
|---|
| 295 | pub(super) kind: TypesKind, | 
|---|
| 296 | } | 
|---|
| 297 |  | 
|---|
| 298 | #[ derive(Clone, Copy)] | 
|---|
| 299 | pub(super) enum TypesRefKind<'a> { | 
|---|
| 300 | Module(&'a Module), | 
|---|
| 301 | #[ cfg(feature = "component-model")] | 
|---|
| 302 | Component(&'a ComponentState), | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | /// Represents the types known to a [`crate::Validator`] during validation. | 
|---|
| 306 | /// | 
|---|
| 307 | /// Retrieved via the [`crate::Validator::types`] method. | 
|---|
| 308 | #[ derive(Clone, Copy)] | 
|---|
| 309 | pub struct TypesRef<'a> { | 
|---|
| 310 | id: ValidatorId, | 
|---|
| 311 | pub(super) list: &'a TypeList, | 
|---|
| 312 | pub(super) kind: TypesRefKind<'a>, | 
|---|
| 313 | } | 
|---|
| 314 |  | 
|---|
| 315 | impl<'a> TypesRef<'a> { | 
|---|
| 316 | pub(crate) fn from_module(id: ValidatorId, types: &'a TypeList, module: &'a Module) -> Self { | 
|---|
| 317 | Self { | 
|---|
| 318 | id, | 
|---|
| 319 | list: types, | 
|---|
| 320 | kind: TypesRefKind::Module(module), | 
|---|
| 321 | } | 
|---|
| 322 | } | 
|---|
| 323 |  | 
|---|
| 324 | #[ cfg(feature = "component-model")] | 
|---|
| 325 | pub(crate) fn from_component( | 
|---|
| 326 | id: ValidatorId, | 
|---|
| 327 | types: &'a TypeList, | 
|---|
| 328 | component: &'a ComponentState, | 
|---|
| 329 | ) -> Self { | 
|---|
| 330 | Self { | 
|---|
| 331 | id, | 
|---|
| 332 | list: types, | 
|---|
| 333 | kind: TypesRefKind::Component(component), | 
|---|
| 334 | } | 
|---|
| 335 | } | 
|---|
| 336 |  | 
|---|
| 337 | /// Get the id of the validator that these types are associated with. | 
|---|
| 338 | #[ inline] | 
|---|
| 339 | pub fn id(&self) -> ValidatorId { | 
|---|
| 340 | self.id | 
|---|
| 341 | } | 
|---|
| 342 |  | 
|---|
| 343 | /// Gets a type based on its type id. | 
|---|
| 344 | /// | 
|---|
| 345 | /// Returns `None` if the type id is unknown. | 
|---|
| 346 | pub fn get<T>(&self, id: T) -> Option<&'a T::Data> | 
|---|
| 347 | where | 
|---|
| 348 | T: TypeIdentifier, | 
|---|
| 349 | { | 
|---|
| 350 | self.list.get(id) | 
|---|
| 351 | } | 
|---|
| 352 |  | 
|---|
| 353 | /// Get the id of the rec group that the given type id was defined within. | 
|---|
| 354 | pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId { | 
|---|
| 355 | self.list.rec_group_id_of(id) | 
|---|
| 356 | } | 
|---|
| 357 |  | 
|---|
| 358 | /// Get the types within a rec group. | 
|---|
| 359 | pub fn rec_group_elements(&self, id: RecGroupId) -> impl ExactSizeIterator<Item = CoreTypeId> { | 
|---|
| 360 | let range = &self.list.rec_group_elements[id]; | 
|---|
| 361 | (range.start.index..range.end.index).map(|index| CoreTypeId { index }) | 
|---|
| 362 | } | 
|---|
| 363 |  | 
|---|
| 364 | /// Get the super type of the given type id, if any. | 
|---|
| 365 | pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> { | 
|---|
| 366 | self.list.supertype_of(id) | 
|---|
| 367 | } | 
|---|
| 368 |  | 
|---|
| 369 | /// Gets a core WebAssembly type id from a type index. | 
|---|
| 370 | /// | 
|---|
| 371 | /// Note that this is not to be confused with | 
|---|
| 372 | /// [`TypesRef::component_type_at`] which gets a component type from its | 
|---|
| 373 | /// index, nor [`TypesRef::core_type_at_in_component`] which is for | 
|---|
| 374 | /// learning about core types in components. | 
|---|
| 375 | /// | 
|---|
| 376 | /// # Panics | 
|---|
| 377 | /// | 
|---|
| 378 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 379 | pub fn core_type_at_in_module(&self, index: u32) -> CoreTypeId { | 
|---|
| 380 | match &self.kind { | 
|---|
| 381 | TypesRefKind::Module(module) => module.types[index as usize].into(), | 
|---|
| 382 | #[ cfg(feature = "component-model")] | 
|---|
| 383 | TypesRefKind::Component(_) => panic!( "use `core_type_at_in_component` instead"), | 
|---|
| 384 | } | 
|---|
| 385 | } | 
|---|
| 386 |  | 
|---|
| 387 | /// Returns the number of core types defined so far. | 
|---|
| 388 | /// | 
|---|
| 389 | /// Note that this is only for core modules, for components you should use | 
|---|
| 390 | /// [`TypesRef::core_type_count_in_component`] instead. | 
|---|
| 391 | pub fn core_type_count_in_module(&self) -> u32 { | 
|---|
| 392 | match &self.kind { | 
|---|
| 393 | TypesRefKind::Module(module) => module.types.len() as u32, | 
|---|
| 394 | #[ cfg(feature = "component-model")] | 
|---|
| 395 | TypesRefKind::Component(_) => 0, | 
|---|
| 396 | } | 
|---|
| 397 | } | 
|---|
| 398 |  | 
|---|
| 399 | /// Gets the type of a table at the given table index. | 
|---|
| 400 | /// | 
|---|
| 401 | /// # Panics | 
|---|
| 402 | /// | 
|---|
| 403 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 404 | pub fn table_at(&self, index: u32) -> TableType { | 
|---|
| 405 | let tables = match &self.kind { | 
|---|
| 406 | TypesRefKind::Module(module) => &module.tables, | 
|---|
| 407 | #[ cfg(feature = "component-model")] | 
|---|
| 408 | TypesRefKind::Component(component) => &component.core_tables, | 
|---|
| 409 | }; | 
|---|
| 410 | tables[index as usize] | 
|---|
| 411 | } | 
|---|
| 412 |  | 
|---|
| 413 | /// Returns the number of tables defined so far. | 
|---|
| 414 | pub fn table_count(&self) -> u32 { | 
|---|
| 415 | match &self.kind { | 
|---|
| 416 | TypesRefKind::Module(module) => module.tables.len() as u32, | 
|---|
| 417 | #[ cfg(feature = "component-model")] | 
|---|
| 418 | TypesRefKind::Component(component) => component.core_tables.len() as u32, | 
|---|
| 419 | } | 
|---|
| 420 | } | 
|---|
| 421 |  | 
|---|
| 422 | /// Gets the type of a memory at the given memory index. | 
|---|
| 423 | /// | 
|---|
| 424 | /// # Panics | 
|---|
| 425 | /// | 
|---|
| 426 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 427 | pub fn memory_at(&self, index: u32) -> MemoryType { | 
|---|
| 428 | let memories = match &self.kind { | 
|---|
| 429 | TypesRefKind::Module(module) => &module.memories, | 
|---|
| 430 | #[ cfg(feature = "component-model")] | 
|---|
| 431 | TypesRefKind::Component(component) => &component.core_memories, | 
|---|
| 432 | }; | 
|---|
| 433 |  | 
|---|
| 434 | memories[index as usize] | 
|---|
| 435 | } | 
|---|
| 436 |  | 
|---|
| 437 | /// Returns the number of memories defined so far. | 
|---|
| 438 | pub fn memory_count(&self) -> u32 { | 
|---|
| 439 | match &self.kind { | 
|---|
| 440 | TypesRefKind::Module(module) => module.memories.len() as u32, | 
|---|
| 441 | #[ cfg(feature = "component-model")] | 
|---|
| 442 | TypesRefKind::Component(component) => component.core_memories.len() as u32, | 
|---|
| 443 | } | 
|---|
| 444 | } | 
|---|
| 445 |  | 
|---|
| 446 | /// Gets the type of a global at the given global index. | 
|---|
| 447 | /// | 
|---|
| 448 | /// # Panics | 
|---|
| 449 | /// | 
|---|
| 450 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 451 | pub fn global_at(&self, index: u32) -> GlobalType { | 
|---|
| 452 | let globals = match &self.kind { | 
|---|
| 453 | TypesRefKind::Module(module) => &module.globals, | 
|---|
| 454 | #[ cfg(feature = "component-model")] | 
|---|
| 455 | TypesRefKind::Component(component) => &component.core_globals, | 
|---|
| 456 | }; | 
|---|
| 457 |  | 
|---|
| 458 | globals[index as usize] | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|
| 461 | /// Returns the number of globals defined so far. | 
|---|
| 462 | pub fn global_count(&self) -> u32 { | 
|---|
| 463 | match &self.kind { | 
|---|
| 464 | TypesRefKind::Module(module) => module.globals.len() as u32, | 
|---|
| 465 | #[ cfg(feature = "component-model")] | 
|---|
| 466 | TypesRefKind::Component(component) => component.core_globals.len() as u32, | 
|---|
| 467 | } | 
|---|
| 468 | } | 
|---|
| 469 |  | 
|---|
| 470 | /// Gets the type of a tag at the given tag index. | 
|---|
| 471 | /// | 
|---|
| 472 | /// # Panics | 
|---|
| 473 | /// | 
|---|
| 474 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 475 | pub fn tag_at(&self, index: u32) -> CoreTypeId { | 
|---|
| 476 | let tags = match &self.kind { | 
|---|
| 477 | TypesRefKind::Module(module) => &module.tags, | 
|---|
| 478 | #[ cfg(feature = "component-model")] | 
|---|
| 479 | TypesRefKind::Component(component) => &component.core_tags, | 
|---|
| 480 | }; | 
|---|
| 481 | tags[index as usize] | 
|---|
| 482 | } | 
|---|
| 483 |  | 
|---|
| 484 | /// Returns the number of tags defined so far. | 
|---|
| 485 | pub fn tag_count(&self) -> u32 { | 
|---|
| 486 | match &self.kind { | 
|---|
| 487 | TypesRefKind::Module(module) => module.tags.len() as u32, | 
|---|
| 488 | #[ cfg(feature = "component-model")] | 
|---|
| 489 | TypesRefKind::Component(component) => component.core_tags.len() as u32, | 
|---|
| 490 | } | 
|---|
| 491 | } | 
|---|
| 492 |  | 
|---|
| 493 | /// Gets the type of a core function at the given function index. | 
|---|
| 494 | /// | 
|---|
| 495 | /// # Panics | 
|---|
| 496 | /// | 
|---|
| 497 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 498 | pub fn core_function_at(&self, index: u32) -> CoreTypeId { | 
|---|
| 499 | match &self.kind { | 
|---|
| 500 | TypesRefKind::Module(module) => module.types[module.functions[index as usize] as usize], | 
|---|
| 501 | #[ cfg(feature = "component-model")] | 
|---|
| 502 | TypesRefKind::Component(component) => component.core_funcs[index as usize], | 
|---|
| 503 | } | 
|---|
| 504 | } | 
|---|
| 505 |  | 
|---|
| 506 | /// Gets the count of core functions defined so far. | 
|---|
| 507 | /// | 
|---|
| 508 | /// Note that this includes imported functions, defined functions, and for | 
|---|
| 509 | /// components lowered/aliased functions. | 
|---|
| 510 | pub fn function_count(&self) -> u32 { | 
|---|
| 511 | match &self.kind { | 
|---|
| 512 | TypesRefKind::Module(module) => module.functions.len() as u32, | 
|---|
| 513 | #[ cfg(feature = "component-model")] | 
|---|
| 514 | TypesRefKind::Component(component) => component.core_funcs.len() as u32, | 
|---|
| 515 | } | 
|---|
| 516 | } | 
|---|
| 517 |  | 
|---|
| 518 | /// Gets the type of an element segment at the given element segment index. | 
|---|
| 519 | /// | 
|---|
| 520 | /// # Panics | 
|---|
| 521 | /// | 
|---|
| 522 | /// This will panic if the `index` provided is out of bounds. | 
|---|
| 523 | pub fn element_at(&self, index: u32) -> RefType { | 
|---|
| 524 | match &self.kind { | 
|---|
| 525 | TypesRefKind::Module(module) => module.element_types[index as usize], | 
|---|
| 526 | #[ cfg(feature = "component-model")] | 
|---|
| 527 | TypesRefKind::Component(_) => { | 
|---|
| 528 | panic!( "no elements on a component") | 
|---|
| 529 | } | 
|---|
| 530 | } | 
|---|
| 531 | } | 
|---|
| 532 |  | 
|---|
| 533 | /// Returns the number of elements defined so far. | 
|---|
| 534 | pub fn element_count(&self) -> u32 { | 
|---|
| 535 | match &self.kind { | 
|---|
| 536 | TypesRefKind::Module(module) => module.element_types.len() as u32, | 
|---|
| 537 | #[ cfg(feature = "component-model")] | 
|---|
| 538 | TypesRefKind::Component(_) => 0, | 
|---|
| 539 | } | 
|---|
| 540 | } | 
|---|
| 541 |  | 
|---|
| 542 | /// Gets the entity type for the given import. | 
|---|
| 543 | pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> { | 
|---|
| 544 | match &self.kind { | 
|---|
| 545 | TypesRefKind::Module(module) => Some(match import.ty { | 
|---|
| 546 | TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?), | 
|---|
| 547 | TypeRef::Table(ty) => EntityType::Table(ty), | 
|---|
| 548 | TypeRef::Memory(ty) => EntityType::Memory(ty), | 
|---|
| 549 | TypeRef::Global(ty) => EntityType::Global(ty), | 
|---|
| 550 | TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?), | 
|---|
| 551 | }), | 
|---|
| 552 | #[ cfg(feature = "component-model")] | 
|---|
| 553 | TypesRefKind::Component(_) => None, | 
|---|
| 554 | } | 
|---|
| 555 | } | 
|---|
| 556 |  | 
|---|
| 557 | /// Gets the entity type from the given export. | 
|---|
| 558 | pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> { | 
|---|
| 559 | match &self.kind { | 
|---|
| 560 | TypesRefKind::Module(module) => Some(match export.kind { | 
|---|
| 561 | ExternalKind::Func => EntityType::Func( | 
|---|
| 562 | module.types[*module.functions.get(export.index as usize)? as usize], | 
|---|
| 563 | ), | 
|---|
| 564 | ExternalKind::Table => { | 
|---|
| 565 | EntityType::Table(*module.tables.get(export.index as usize)?) | 
|---|
| 566 | } | 
|---|
| 567 | ExternalKind::Memory => { | 
|---|
| 568 | EntityType::Memory(*module.memories.get(export.index as usize)?) | 
|---|
| 569 | } | 
|---|
| 570 | ExternalKind::Global => { | 
|---|
| 571 | EntityType::Global(*module.globals.get(export.index as usize)?) | 
|---|
| 572 | } | 
|---|
| 573 | ExternalKind::Tag => EntityType::Tag( | 
|---|
| 574 | module.types[*module.functions.get(export.index as usize)? as usize], | 
|---|
| 575 | ), | 
|---|
| 576 | }), | 
|---|
| 577 | #[ cfg(feature = "component-model")] | 
|---|
| 578 | TypesRefKind::Component(_) => None, | 
|---|
| 579 | } | 
|---|
| 580 | } | 
|---|
| 581 |  | 
|---|
| 582 | /// Returns an iterator over the core wasm imports found. | 
|---|
| 583 | /// | 
|---|
| 584 | /// Returns `None` if this type information is for a component. | 
|---|
| 585 | pub fn core_imports( | 
|---|
| 586 | &self, | 
|---|
| 587 | ) -> Option<impl Iterator<Item = (&'a str, &'a str, EntityType)> + 'a> { | 
|---|
| 588 | match &self.kind { | 
|---|
| 589 | TypesRefKind::Module(module) => Some( | 
|---|
| 590 | module | 
|---|
| 591 | .imports | 
|---|
| 592 | .iter() | 
|---|
| 593 | .flat_map(|((m, n), t)| t.iter().map(move |t| (m.as_str(), n.as_str(), *t))), | 
|---|
| 594 | ), | 
|---|
| 595 | #[ cfg(feature = "component-model")] | 
|---|
| 596 | TypesRefKind::Component(_) => None, | 
|---|
| 597 | } | 
|---|
| 598 | } | 
|---|
| 599 |  | 
|---|
| 600 | /// Returns an iterator over the core wasm exports found. | 
|---|
| 601 | /// | 
|---|
| 602 | /// Returns `None` if this type information is for a component. | 
|---|
| 603 | pub fn core_exports(&self) -> Option<impl Iterator<Item = (&'a str, EntityType)> + 'a> { | 
|---|
| 604 | match &self.kind { | 
|---|
| 605 | TypesRefKind::Module(module) => { | 
|---|
| 606 | Some(module.exports.iter().map(|(n, t)| (n.as_str(), *t))) | 
|---|
| 607 | } | 
|---|
| 608 | #[ cfg(feature = "component-model")] | 
|---|
| 609 | TypesRefKind::Component(_) => None, | 
|---|
| 610 | } | 
|---|
| 611 | } | 
|---|
| 612 | } | 
|---|
| 613 |  | 
|---|
| 614 | impl<T> Index<T> for TypesRef<'_> | 
|---|
| 615 | where | 
|---|
| 616 | T: TypeIdentifier, | 
|---|
| 617 | { | 
|---|
| 618 | type Output = T::Data; | 
|---|
| 619 |  | 
|---|
| 620 | fn index(&self, index: T) -> &Self::Output { | 
|---|
| 621 | &self.list[index] | 
|---|
| 622 | } | 
|---|
| 623 | } | 
|---|
| 624 |  | 
|---|
| 625 | impl Types { | 
|---|
| 626 | pub(crate) fn from_module(id: ValidatorId, types: TypeList, module: Arc<Module>) -> Self { | 
|---|
| 627 | Self { | 
|---|
| 628 | id, | 
|---|
| 629 | list: types, | 
|---|
| 630 | kind: TypesKind::Module(module), | 
|---|
| 631 | } | 
|---|
| 632 | } | 
|---|
| 633 |  | 
|---|
| 634 | #[ cfg(feature = "component-model")] | 
|---|
| 635 | pub(crate) fn from_component( | 
|---|
| 636 | id: ValidatorId, | 
|---|
| 637 | types: TypeList, | 
|---|
| 638 | component: ComponentState, | 
|---|
| 639 | ) -> Self { | 
|---|
| 640 | Self { | 
|---|
| 641 | id, | 
|---|
| 642 | list: types, | 
|---|
| 643 | kind: TypesKind::Component(component), | 
|---|
| 644 | } | 
|---|
| 645 | } | 
|---|
| 646 |  | 
|---|
| 647 | /// Return a [`TypesRef`] through which types can be inspected. | 
|---|
| 648 | pub fn as_ref(&self) -> TypesRef<'_> { | 
|---|
| 649 | TypesRef { | 
|---|
| 650 | id: self.id, | 
|---|
| 651 | list: &self.list, | 
|---|
| 652 | kind: match &self.kind { | 
|---|
| 653 | TypesKind::Module(module) => TypesRefKind::Module(module), | 
|---|
| 654 | #[ cfg(feature = "component-model")] | 
|---|
| 655 | TypesKind::Component(component) => TypesRefKind::Component(component), | 
|---|
| 656 | }, | 
|---|
| 657 | } | 
|---|
| 658 | } | 
|---|
| 659 | } | 
|---|
| 660 |  | 
|---|
| 661 | impl<T> Index<T> for Types | 
|---|
| 662 | where | 
|---|
| 663 | T: TypeIdentifier, | 
|---|
| 664 | { | 
|---|
| 665 | type Output = T::Data; | 
|---|
| 666 |  | 
|---|
| 667 | fn index(&self, id: T) -> &Self::Output { | 
|---|
| 668 | &self.list[id] | 
|---|
| 669 | } | 
|---|
| 670 | } | 
|---|
| 671 |  | 
|---|
| 672 | /// This is a type which mirrors a subset of the `Vec<T>` API, but is intended | 
|---|
| 673 | /// to be able to be cheaply snapshotted and cloned. | 
|---|
| 674 | /// | 
|---|
| 675 | /// When each module's code sections start we "commit" the current list of types | 
|---|
| 676 | /// in the global list of types. This means that the temporary `cur` vec here is | 
|---|
| 677 | /// pushed onto `snapshots` and wrapped up in an `Arc`. At that point we clone | 
|---|
| 678 | /// this entire list (which is then O(modules), not O(types in all modules)) and | 
|---|
| 679 | /// pass out as a context to each function validator. | 
|---|
| 680 | /// | 
|---|
| 681 | /// Otherwise, though, this type behaves as if it were a large `Vec<T>`, but | 
|---|
| 682 | /// it's represented by lists of contiguous chunks. | 
|---|
| 683 | // | 
|---|
| 684 | // Only public because it shows up in a public trait's `doc(hidden)` method. | 
|---|
| 685 | #[ doc(hidden)] | 
|---|
| 686 | #[ derive(Debug)] | 
|---|
| 687 | pub struct SnapshotList<T> { | 
|---|
| 688 | // All previous snapshots, the "head" of the list that this type represents. | 
|---|
| 689 | // The first entry in this pair is the starting index for all elements | 
|---|
| 690 | // contained in the list, and the second element is the list itself. Note | 
|---|
| 691 | // the `Arc` wrapper around sub-lists, which makes cloning time for this | 
|---|
| 692 | // `SnapshotList` O(snapshots) rather than O(snapshots_total), which for | 
|---|
| 693 | // us in this context means the number of modules, not types. | 
|---|
| 694 | // | 
|---|
| 695 | // Note that this list is sorted least-to-greatest in order of the index for | 
|---|
| 696 | // binary searching. | 
|---|
| 697 | snapshots: Vec<Arc<Snapshot<T>>>, | 
|---|
| 698 |  | 
|---|
| 699 | // This is the total length of all lists in the `snapshots` array. | 
|---|
| 700 | snapshots_total: usize, | 
|---|
| 701 |  | 
|---|
| 702 | // The current list of types for the current snapshot that are being built. | 
|---|
| 703 | cur: Vec<T>, | 
|---|
| 704 | } | 
|---|
| 705 |  | 
|---|
| 706 | #[ derive(Debug)] | 
|---|
| 707 | struct Snapshot<T> { | 
|---|
| 708 | prior_types: usize, | 
|---|
| 709 | items: Vec<T>, | 
|---|
| 710 | } | 
|---|
| 711 |  | 
|---|
| 712 | impl<T> SnapshotList<T> { | 
|---|
| 713 | /// Same as `<&[T]>::get` | 
|---|
| 714 | pub(crate) fn get(&self, index: usize) -> Option<&T> { | 
|---|
| 715 | // Check to see if this index falls on our local list | 
|---|
| 716 | if index >= self.snapshots_total { | 
|---|
| 717 | return self.cur.get(index - self.snapshots_total); | 
|---|
| 718 | } | 
|---|
| 719 | // ... and failing that we do a binary search to figure out which bucket | 
|---|
| 720 | // it's in. Note the `i-1` in the `Err` case because if we don't find an | 
|---|
| 721 | // exact match the type is located in the previous bucket. | 
|---|
| 722 | let i = match self | 
|---|
| 723 | .snapshots | 
|---|
| 724 | .binary_search_by_key(&index, |snapshot| snapshot.prior_types) | 
|---|
| 725 | { | 
|---|
| 726 | Ok(i) => i, | 
|---|
| 727 | Err(i) => i - 1, | 
|---|
| 728 | }; | 
|---|
| 729 | let snapshot = &self.snapshots[i]; | 
|---|
| 730 | Some(&snapshot.items[index - snapshot.prior_types]) | 
|---|
| 731 | } | 
|---|
| 732 |  | 
|---|
| 733 | /// Same as `Vec::push` | 
|---|
| 734 | pub(crate) fn push(&mut self, val: T) { | 
|---|
| 735 | self.cur.push(val); | 
|---|
| 736 | } | 
|---|
| 737 |  | 
|---|
| 738 | /// Same as `<[T]>::len` | 
|---|
| 739 | pub(crate) fn len(&self) -> usize { | 
|---|
| 740 | self.cur.len() + self.snapshots_total | 
|---|
| 741 | } | 
|---|
| 742 |  | 
|---|
| 743 | /// Same as `Vec::truncate` but can only truncate uncommitted elements. | 
|---|
| 744 | #[ cfg(feature = "component-model")] | 
|---|
| 745 | pub(crate) fn truncate(&mut self, len: usize) { | 
|---|
| 746 | assert!(len >= self.snapshots_total); | 
|---|
| 747 | self.cur.truncate(len - self.snapshots_total); | 
|---|
| 748 | } | 
|---|
| 749 |  | 
|---|
| 750 | /// Commits previously pushed types into this snapshot vector, and returns a | 
|---|
| 751 | /// clone of this list. | 
|---|
| 752 | /// | 
|---|
| 753 | /// The returned `SnapshotList` can be used to access all the same types as | 
|---|
| 754 | /// this list itself. This list also is not changed (from an external | 
|---|
| 755 | /// perspective) and can continue to access all the same types. | 
|---|
| 756 | pub(crate) fn commit(&mut self) -> SnapshotList<T> { | 
|---|
| 757 | // If the current chunk has new elements, commit them in to an | 
|---|
| 758 | // `Arc`-wrapped vector in the snapshots list. Note the `shrink_to_fit` | 
|---|
| 759 | // ahead of time to hopefully keep memory usage lower than it would | 
|---|
| 760 | // otherwise be. | 
|---|
| 761 | let len = self.cur.len(); | 
|---|
| 762 | if len > 0 { | 
|---|
| 763 | self.cur.shrink_to_fit(); | 
|---|
| 764 | self.snapshots.push(Arc::new(Snapshot { | 
|---|
| 765 | prior_types: self.snapshots_total, | 
|---|
| 766 | items: mem::take(&mut self.cur), | 
|---|
| 767 | })); | 
|---|
| 768 | self.snapshots_total += len; | 
|---|
| 769 | } | 
|---|
| 770 | SnapshotList { | 
|---|
| 771 | snapshots: self.snapshots.clone(), | 
|---|
| 772 | snapshots_total: self.snapshots_total, | 
|---|
| 773 | cur: Vec::new(), | 
|---|
| 774 | } | 
|---|
| 775 | } | 
|---|
| 776 | } | 
|---|
| 777 |  | 
|---|
| 778 | impl<T> Index<usize> for SnapshotList<T> { | 
|---|
| 779 | type Output = T; | 
|---|
| 780 |  | 
|---|
| 781 | #[ inline] | 
|---|
| 782 | fn index(&self, index: usize) -> &T { | 
|---|
| 783 | self.get(index).unwrap() | 
|---|
| 784 | } | 
|---|
| 785 | } | 
|---|
| 786 |  | 
|---|
| 787 | impl<T, U> Index<U> for SnapshotList<T> | 
|---|
| 788 | where | 
|---|
| 789 | U: TypeIdentifier<Data = T>, | 
|---|
| 790 | { | 
|---|
| 791 | type Output = T; | 
|---|
| 792 |  | 
|---|
| 793 | #[ inline] | 
|---|
| 794 | fn index(&self, id: U) -> &T { | 
|---|
| 795 | self.get(id.index()).unwrap() | 
|---|
| 796 | } | 
|---|
| 797 | } | 
|---|
| 798 |  | 
|---|
| 799 | impl<T> Default for SnapshotList<T> { | 
|---|
| 800 | fn default() -> SnapshotList<T> { | 
|---|
| 801 | SnapshotList { | 
|---|
| 802 | snapshots: Vec::new(), | 
|---|
| 803 | snapshots_total: 0, | 
|---|
| 804 | cur: Vec::new(), | 
|---|
| 805 | } | 
|---|
| 806 | } | 
|---|
| 807 | } | 
|---|
| 808 |  | 
|---|
| 809 | /// A snapshot list of types. | 
|---|
| 810 | /// | 
|---|
| 811 | /// Note that the snapshot lists below do not correspond with index spaces. Many | 
|---|
| 812 | /// different kinds of types are in the same index space (e.g. all of the | 
|---|
| 813 | /// component model's {component, instance, defined, func} types are in the same | 
|---|
| 814 | /// index space). However, we store each of them in their own type-specific | 
|---|
| 815 | /// snapshot list and give each of them their own identifier type. | 
|---|
| 816 | #[ derive(Default, Debug)] | 
|---|
| 817 | // Only public because it shows up in a public trait's `doc(hidden)` method. | 
|---|
| 818 | #[ doc(hidden)] | 
|---|
| 819 | pub struct TypeList { | 
|---|
| 820 | // Core Wasm types. | 
|---|
| 821 | // | 
|---|
| 822 | // A primary map from `CoreTypeId` to `SubType`. | 
|---|
| 823 | pub(super) core_types: SnapshotList<SubType>, | 
|---|
| 824 | // The id of each core Wasm type's rec group. | 
|---|
| 825 | // | 
|---|
| 826 | // A secondary map from `CoreTypeId` to `RecGroupId`. | 
|---|
| 827 | pub(super) core_type_to_rec_group: SnapshotList<RecGroupId>, | 
|---|
| 828 | // The supertype of each core type. | 
|---|
| 829 | // | 
|---|
| 830 | // A secondary map from `CoreTypeId` to `Option<CoreTypeId>`. | 
|---|
| 831 | pub(super) core_type_to_supertype: SnapshotList<Option<CoreTypeId>>, | 
|---|
| 832 | // The subtyping depth of each core type. We use `u8::MAX` as a sentinel for | 
|---|
| 833 | // an uninitialized entry. | 
|---|
| 834 | // | 
|---|
| 835 | // A secondary map from `CoreTypeId` to `u8`. | 
|---|
| 836 | pub(super) core_type_to_depth: Option<IndexMap<CoreTypeId, u8>>, | 
|---|
| 837 | // A primary map from `RecGroupId` to the range of the rec group's elements | 
|---|
| 838 | // within `core_types`. | 
|---|
| 839 | pub(super) rec_group_elements: SnapshotList<Range<CoreTypeId>>, | 
|---|
| 840 | // A hash map from rec group elements to their canonical `RecGroupId`. | 
|---|
| 841 | // | 
|---|
| 842 | // This is `None` when a list is "committed" meaning that no more insertions | 
|---|
| 843 | // can happen. | 
|---|
| 844 | pub(super) canonical_rec_groups: Option<Map<RecGroup, RecGroupId>>, | 
|---|
| 845 |  | 
|---|
| 846 | #[ cfg(feature = "component-model")] | 
|---|
| 847 | pub(super) component: ComponentTypeList, | 
|---|
| 848 | } | 
|---|
| 849 |  | 
|---|
| 850 | impl TypeList { | 
|---|
| 851 | pub fn get<T>(&self, id: T) -> Option<&T::Data> | 
|---|
| 852 | where | 
|---|
| 853 | T: TypeIdentifier, | 
|---|
| 854 | { | 
|---|
| 855 | T::list(self).get(id.index()) | 
|---|
| 856 | } | 
|---|
| 857 |  | 
|---|
| 858 | pub fn push<T>(&mut self, ty: T) -> T::Id | 
|---|
| 859 | where | 
|---|
| 860 | T: TypeData, | 
|---|
| 861 | { | 
|---|
| 862 | let index = u32::try_from(T::Id::list(self).len()).unwrap(); | 
|---|
| 863 | let id = T::Id::from_index(index); | 
|---|
| 864 | T::Id::list_mut(self).push(ty); | 
|---|
| 865 | id | 
|---|
| 866 | } | 
|---|
| 867 |  | 
|---|
| 868 | /// Intern the given recursion group (that has already been canonicalized) | 
|---|
| 869 | /// and return its associated id and whether this was a new recursion group | 
|---|
| 870 | /// or not. | 
|---|
| 871 | /// | 
|---|
| 872 | /// If the `needs_type_canonicalization` flag is provided then the type will | 
|---|
| 873 | /// be intern'd here and its indices will be canonicalized to `CoreTypeId` | 
|---|
| 874 | /// from the previous `RecGroup`-based indices. | 
|---|
| 875 | /// | 
|---|
| 876 | /// If the `needs_type_canonicalization` flag is `false` then it must be | 
|---|
| 877 | /// required that `RecGroup` doesn't have any rec-group-relative references | 
|---|
| 878 | /// and it will additionally not be intern'd. | 
|---|
| 879 | pub fn intern_canonical_rec_group( | 
|---|
| 880 | &mut self, | 
|---|
| 881 | needs_type_canonicalization: bool, | 
|---|
| 882 | mut rec_group: RecGroup, | 
|---|
| 883 | ) -> (bool, RecGroupId) { | 
|---|
| 884 | let rec_group_id = self.rec_group_elements.len(); | 
|---|
| 885 | let rec_group_id = u32::try_from(rec_group_id).unwrap(); | 
|---|
| 886 | let rec_group_id = RecGroupId::from_index(rec_group_id); | 
|---|
| 887 |  | 
|---|
| 888 | if needs_type_canonicalization { | 
|---|
| 889 | let canonical_rec_groups = self | 
|---|
| 890 | .canonical_rec_groups | 
|---|
| 891 | .as_mut() | 
|---|
| 892 | .expect( "cannot intern into a committed list"); | 
|---|
| 893 | let entry = match canonical_rec_groups.entry(rec_group) { | 
|---|
| 894 | Entry::Occupied(e) => return (false, *e.get()), | 
|---|
| 895 | Entry::Vacant(e) => e, | 
|---|
| 896 | }; | 
|---|
| 897 | rec_group = entry.key().clone(); | 
|---|
| 898 | entry.insert(rec_group_id); | 
|---|
| 899 | } | 
|---|
| 900 |  | 
|---|
| 901 | let start = self.core_types.len(); | 
|---|
| 902 | let start = u32::try_from(start).unwrap(); | 
|---|
| 903 | let start = CoreTypeId::from_index(start); | 
|---|
| 904 |  | 
|---|
| 905 | for mut ty in rec_group.into_types() { | 
|---|
| 906 | debug_assert_eq!(self.core_types.len(), self.core_type_to_supertype.len()); | 
|---|
| 907 | debug_assert_eq!(self.core_types.len(), self.core_type_to_rec_group.len()); | 
|---|
| 908 |  | 
|---|
| 909 | self.core_type_to_supertype | 
|---|
| 910 | .push(ty.supertype_idx.and_then(|idx| match idx.unpack() { | 
|---|
| 911 | UnpackedIndex::RecGroup(offset) => { | 
|---|
| 912 | Some(CoreTypeId::from_index(start.index + offset)) | 
|---|
| 913 | } | 
|---|
| 914 | UnpackedIndex::Id(id) => Some(id), | 
|---|
| 915 | // Only invalid wasm has this, at this point, so defer the | 
|---|
| 916 | // error to later. | 
|---|
| 917 | UnpackedIndex::Module(_) => None, | 
|---|
| 918 | })); | 
|---|
| 919 | ty.remap_indices(&mut |index| { | 
|---|
| 920 | // Note that `UnpackedIndex::Id` is unmodified and | 
|---|
| 921 | // `UnpackedIndex::Module` means that this is invalid wasm which | 
|---|
| 922 | // will get an error returned later. | 
|---|
| 923 | if let UnpackedIndex::RecGroup(offset) = index.unpack() { | 
|---|
| 924 | *index = UnpackedIndex::Id(CoreTypeId::from_index(start.index + offset)) | 
|---|
| 925 | .pack() | 
|---|
| 926 | .unwrap(); | 
|---|
| 927 | } | 
|---|
| 928 | Ok(()) | 
|---|
| 929 | }) | 
|---|
| 930 | .expect( "cannot fail"); | 
|---|
| 931 | self.core_types.push(ty); | 
|---|
| 932 | self.core_type_to_rec_group.push(rec_group_id); | 
|---|
| 933 | } | 
|---|
| 934 |  | 
|---|
| 935 | let end = self.core_types.len(); | 
|---|
| 936 | let end = u32::try_from(end).unwrap(); | 
|---|
| 937 | let end = CoreTypeId::from_index(end); | 
|---|
| 938 |  | 
|---|
| 939 | let range = start..end; | 
|---|
| 940 |  | 
|---|
| 941 | self.rec_group_elements.push(range.clone()); | 
|---|
| 942 |  | 
|---|
| 943 | return (true, rec_group_id); | 
|---|
| 944 | } | 
|---|
| 945 |  | 
|---|
| 946 | /// Helper for interning a sub type as a rec group; see | 
|---|
| 947 | /// [`Self::intern_canonical_rec_group`]. | 
|---|
| 948 | pub fn intern_sub_type(&mut self, sub_ty: SubType, offset: usize) -> CoreTypeId { | 
|---|
| 949 | let (_is_new, group_id) = | 
|---|
| 950 | self.intern_canonical_rec_group(false, RecGroup::implicit(offset, sub_ty)); | 
|---|
| 951 | self[group_id].start | 
|---|
| 952 | } | 
|---|
| 953 |  | 
|---|
| 954 | /// Helper for interning a function type as a rec group; see | 
|---|
| 955 | /// [`Self::intern_sub_type`]. | 
|---|
| 956 | pub fn intern_func_type(&mut self, ty: FuncType, offset: usize) -> CoreTypeId { | 
|---|
| 957 | self.intern_sub_type(SubType::func(ty, false), offset) | 
|---|
| 958 | } | 
|---|
| 959 |  | 
|---|
| 960 | /// Get the `CoreTypeId` for a local index into a rec group. | 
|---|
| 961 | pub fn rec_group_local_id( | 
|---|
| 962 | &self, | 
|---|
| 963 | rec_group: RecGroupId, | 
|---|
| 964 | index: u32, | 
|---|
| 965 | offset: usize, | 
|---|
| 966 | ) -> Result<CoreTypeId> { | 
|---|
| 967 | let elems = &self[rec_group]; | 
|---|
| 968 | let len = elems.end.index() - elems.start.index(); | 
|---|
| 969 | let len = u32::try_from(len).unwrap(); | 
|---|
| 970 | if index < len { | 
|---|
| 971 | let id = u32::try_from(elems.start.index()).unwrap() + index; | 
|---|
| 972 | let id = CoreTypeId::from_index(id); | 
|---|
| 973 | Ok(id) | 
|---|
| 974 | } else { | 
|---|
| 975 | bail!( | 
|---|
| 976 | offset, | 
|---|
| 977 | "unknown type {index} : type index out of rec group bounds" | 
|---|
| 978 | ) | 
|---|
| 979 | } | 
|---|
| 980 | } | 
|---|
| 981 |  | 
|---|
| 982 | /// Get the id of the rec group that the given type id was defined within. | 
|---|
| 983 | pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId { | 
|---|
| 984 | self.core_type_to_rec_group[id.index()] | 
|---|
| 985 | } | 
|---|
| 986 |  | 
|---|
| 987 | /// Get the super type of the given type id, if any. | 
|---|
| 988 | pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> { | 
|---|
| 989 | self.core_type_to_supertype[id.index()] | 
|---|
| 990 | } | 
|---|
| 991 |  | 
|---|
| 992 | /// Get the subtyping depth of the given type. A type without any supertype | 
|---|
| 993 | /// has depth 0. | 
|---|
| 994 | pub fn get_subtyping_depth(&self, id: CoreTypeId) -> u8 { | 
|---|
| 995 | let depth = self | 
|---|
| 996 | .core_type_to_depth | 
|---|
| 997 | .as_ref() | 
|---|
| 998 | .expect( "cannot get subtype depth from a committed list")[&id]; | 
|---|
| 999 | debug_assert!(usize::from(depth) <= crate::limits::MAX_WASM_SUBTYPING_DEPTH); | 
|---|
| 1000 | depth | 
|---|
| 1001 | } | 
|---|
| 1002 |  | 
|---|
| 1003 | /// Set the subtyping depth of the given type. This may only be done once | 
|---|
| 1004 | /// per type. | 
|---|
| 1005 | pub fn set_subtyping_depth(&mut self, id: CoreTypeId, depth: u8) { | 
|---|
| 1006 | debug_assert!(usize::from(depth) <= crate::limits::MAX_WASM_SUBTYPING_DEPTH); | 
|---|
| 1007 | let map = self | 
|---|
| 1008 | .core_type_to_depth | 
|---|
| 1009 | .as_mut() | 
|---|
| 1010 | .expect( "cannot set a subtype depth in a committed list"); | 
|---|
| 1011 | debug_assert!(!map.contains_key(&id)); | 
|---|
| 1012 | map.insert(id, depth); | 
|---|
| 1013 | } | 
|---|
| 1014 |  | 
|---|
| 1015 | /// Get the `CoreTypeId` for a canonicalized `PackedIndex`. | 
|---|
| 1016 | /// | 
|---|
| 1017 | /// Panics when given a non-canonicalized `PackedIndex`. | 
|---|
| 1018 | pub fn at_canonicalized_packed_index( | 
|---|
| 1019 | &self, | 
|---|
| 1020 | rec_group: RecGroupId, | 
|---|
| 1021 | index: PackedIndex, | 
|---|
| 1022 | offset: usize, | 
|---|
| 1023 | ) -> Result<CoreTypeId> { | 
|---|
| 1024 | self.at_canonicalized_unpacked_index(rec_group, index.unpack(), offset) | 
|---|
| 1025 | } | 
|---|
| 1026 |  | 
|---|
| 1027 | /// Get the `CoreTypeId` for a canonicalized `UnpackedIndex`. | 
|---|
| 1028 | /// | 
|---|
| 1029 | /// Panics when given a non-canonicalized `PackedIndex`. | 
|---|
| 1030 | pub fn at_canonicalized_unpacked_index( | 
|---|
| 1031 | &self, | 
|---|
| 1032 | rec_group: RecGroupId, | 
|---|
| 1033 | index: UnpackedIndex, | 
|---|
| 1034 | offset: usize, | 
|---|
| 1035 | ) -> Result<CoreTypeId> { | 
|---|
| 1036 | match index { | 
|---|
| 1037 | UnpackedIndex::Module(_) => panic!( "not canonicalized"), | 
|---|
| 1038 | UnpackedIndex::Id(id) => Ok(id), | 
|---|
| 1039 | UnpackedIndex::RecGroup(idx) => self.rec_group_local_id(rec_group, idx, offset), | 
|---|
| 1040 | } | 
|---|
| 1041 | } | 
|---|
| 1042 |  | 
|---|
| 1043 | /// Does `a` structurally match `b`? | 
|---|
| 1044 | pub fn matches(&self, a: CoreTypeId, b: CoreTypeId) -> bool { | 
|---|
| 1045 | let a = WithRecGroup::new(self, a); | 
|---|
| 1046 | let a = WithRecGroup::map(a, |a| &self[a]); | 
|---|
| 1047 |  | 
|---|
| 1048 | let b = WithRecGroup::new(self, b); | 
|---|
| 1049 | let b = WithRecGroup::map(b, |b| &self[b]); | 
|---|
| 1050 |  | 
|---|
| 1051 | Matches::matches(self, a, b) | 
|---|
| 1052 | } | 
|---|
| 1053 |  | 
|---|
| 1054 | /// Is `a == b` or was `a` declared (potentially transitively) to be a | 
|---|
| 1055 | /// subtype of `b`? | 
|---|
| 1056 | pub fn id_is_subtype(&self, mut a: CoreTypeId, b: CoreTypeId) -> bool { | 
|---|
| 1057 | loop { | 
|---|
| 1058 | if a == b { | 
|---|
| 1059 | return true; | 
|---|
| 1060 | } | 
|---|
| 1061 |  | 
|---|
| 1062 | // TODO: maintain supertype vectors and implement this check in O(1) | 
|---|
| 1063 | // instead of O(n) time. | 
|---|
| 1064 | a = match self.supertype_of(a) { | 
|---|
| 1065 | Some(a) => a, | 
|---|
| 1066 | None => return false, | 
|---|
| 1067 | }; | 
|---|
| 1068 | } | 
|---|
| 1069 | } | 
|---|
| 1070 |  | 
|---|
| 1071 | /// Like `id_is_subtype` but for `RefType`s. | 
|---|
| 1072 | /// | 
|---|
| 1073 | /// Both `a` and `b` must be canonicalized already. | 
|---|
| 1074 | pub fn reftype_is_subtype(&self, a: RefType, b: RefType) -> bool { | 
|---|
| 1075 | // NB: Don't need `RecGroupId`s since we are calling from outside of the | 
|---|
| 1076 | // rec group, and so any `PackedIndex`es we encounter have already been | 
|---|
| 1077 | // canonicalized to `CoreTypeId`s directly. | 
|---|
| 1078 | self.reftype_is_subtype_impl(a, None, b, None) | 
|---|
| 1079 | } | 
|---|
| 1080 |  | 
|---|
| 1081 | /// Implementation of `RefType` and `HeapType` subtyping. | 
|---|
| 1082 | /// | 
|---|
| 1083 | /// Panics if we need rec groups but aren't given them. Rec groups only need | 
|---|
| 1084 | /// to be passed in when checking subtyping of `RefType`s that we encounter | 
|---|
| 1085 | /// while validating a rec group itself. | 
|---|
| 1086 | pub(crate) fn reftype_is_subtype_impl( | 
|---|
| 1087 | &self, | 
|---|
| 1088 | a: RefType, | 
|---|
| 1089 | a_group: Option<RecGroupId>, | 
|---|
| 1090 | b: RefType, | 
|---|
| 1091 | b_group: Option<RecGroupId>, | 
|---|
| 1092 | ) -> bool { | 
|---|
| 1093 | if a == b && a_group == b_group { | 
|---|
| 1094 | return true; | 
|---|
| 1095 | } | 
|---|
| 1096 |  | 
|---|
| 1097 | if a.is_nullable() && !b.is_nullable() { | 
|---|
| 1098 | return false; | 
|---|
| 1099 | } | 
|---|
| 1100 |  | 
|---|
| 1101 | let core_type_id = |group: Option<RecGroupId>, index: UnpackedIndex| -> CoreTypeId { | 
|---|
| 1102 | if let Some(id) = index.as_core_type_id() { | 
|---|
| 1103 | id | 
|---|
| 1104 | } else { | 
|---|
| 1105 | self.at_canonicalized_unpacked_index(group.unwrap(), index, usize::MAX) | 
|---|
| 1106 | .expect( "type references are checked during canonicalization") | 
|---|
| 1107 | } | 
|---|
| 1108 | }; | 
|---|
| 1109 |  | 
|---|
| 1110 | let subtype = |group, index| -> &SubType { | 
|---|
| 1111 | let id = core_type_id(group, index); | 
|---|
| 1112 | &self[id] | 
|---|
| 1113 | }; | 
|---|
| 1114 |  | 
|---|
| 1115 | use AbstractHeapType::*; | 
|---|
| 1116 | use CompositeInnerType as CT; | 
|---|
| 1117 | use HeapType as HT; | 
|---|
| 1118 | match (a.heap_type(), b.heap_type()) { | 
|---|
| 1119 | (a, b) if a == b => true, | 
|---|
| 1120 |  | 
|---|
| 1121 | ( | 
|---|
| 1122 | HT::Abstract { | 
|---|
| 1123 | shared: a_shared, | 
|---|
| 1124 | ty: a_ty, | 
|---|
| 1125 | }, | 
|---|
| 1126 | HT::Abstract { | 
|---|
| 1127 | shared: b_shared, | 
|---|
| 1128 | ty: b_ty, | 
|---|
| 1129 | }, | 
|---|
| 1130 | ) => a_shared == b_shared && a_ty.is_subtype_of(b_ty), | 
|---|
| 1131 |  | 
|---|
| 1132 | (HT::Concrete(a), HT::Abstract { shared, ty }) => { | 
|---|
| 1133 | let a_ty = &subtype(a_group, a).composite_type; | 
|---|
| 1134 | if a_ty.shared != shared { | 
|---|
| 1135 | return false; | 
|---|
| 1136 | } | 
|---|
| 1137 | match ty { | 
|---|
| 1138 | Any | Eq => matches!(a_ty.inner, CT::Array(_) | CT::Struct(_)), | 
|---|
| 1139 | Struct => matches!(a_ty.inner, CT::Struct(_)), | 
|---|
| 1140 | Array => matches!(a_ty.inner, CT::Array(_)), | 
|---|
| 1141 | Func => matches!(a_ty.inner, CT::Func(_)), | 
|---|
| 1142 | Cont => matches!(a_ty.inner, CT::Cont(_)), | 
|---|
| 1143 | // Nothing else matches. (Avoid full wildcard matches so | 
|---|
| 1144 | // that adding/modifying variants is easier in the future.) | 
|---|
| 1145 | Extern | Exn | I31 | None | NoFunc | NoExtern | NoExn | NoCont => false, | 
|---|
| 1146 | } | 
|---|
| 1147 | } | 
|---|
| 1148 |  | 
|---|
| 1149 | (HT::Abstract { shared, ty }, HT::Concrete(b)) => { | 
|---|
| 1150 | let b_ty = &subtype(b_group, b).composite_type; | 
|---|
| 1151 | if shared != b_ty.shared { | 
|---|
| 1152 | return false; | 
|---|
| 1153 | } | 
|---|
| 1154 | match ty { | 
|---|
| 1155 | None => matches!(b_ty.inner, CT::Array(_) | CT::Struct(_)), | 
|---|
| 1156 | NoFunc => matches!(b_ty.inner, CT::Func(_)), | 
|---|
| 1157 | NoCont => matches!(b_ty.inner, CT::Cont(_)), | 
|---|
| 1158 | // Nothing else matches. (Avoid full wildcard matches so | 
|---|
| 1159 | // that adding/modifying variants is easier in the future.) | 
|---|
| 1160 | Cont | Func | Extern | Exn | Any | Eq | Array | I31 | Struct | NoExtern | 
|---|
| 1161 | | NoExn => false, | 
|---|
| 1162 | } | 
|---|
| 1163 | } | 
|---|
| 1164 |  | 
|---|
| 1165 | (HT::Concrete(a), HT::Concrete(b)) => { | 
|---|
| 1166 | self.id_is_subtype(core_type_id(a_group, a), core_type_id(b_group, b)) | 
|---|
| 1167 | } | 
|---|
| 1168 | } | 
|---|
| 1169 | } | 
|---|
| 1170 |  | 
|---|
| 1171 | /// Like `id_is_subtype` but for `RefType`s. | 
|---|
| 1172 | /// | 
|---|
| 1173 | /// Both `a` and `b` must be canonicalized already. | 
|---|
| 1174 | pub fn valtype_is_subtype(&self, a: ValType, b: ValType) -> bool { | 
|---|
| 1175 | match (a, b) { | 
|---|
| 1176 | (a, b) if a == b => true, | 
|---|
| 1177 | (ValType::Ref(a), ValType::Ref(b)) => self.reftype_is_subtype(a, b), | 
|---|
| 1178 | (ValType::Ref(_), _) | 
|---|
| 1179 | | (ValType::I32, _) | 
|---|
| 1180 | | (ValType::I64, _) | 
|---|
| 1181 | | (ValType::F32, _) | 
|---|
| 1182 | | (ValType::F64, _) | 
|---|
| 1183 | | (ValType::V128, _) => false, | 
|---|
| 1184 | } | 
|---|
| 1185 | } | 
|---|
| 1186 |  | 
|---|
| 1187 | /// Is `ty` shared? | 
|---|
| 1188 | pub fn valtype_is_shared(&self, ty: ValType) -> bool { | 
|---|
| 1189 | match ty { | 
|---|
| 1190 | ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => true, | 
|---|
| 1191 | ValType::Ref(rt) => self.reftype_is_shared(rt), | 
|---|
| 1192 | } | 
|---|
| 1193 | } | 
|---|
| 1194 |  | 
|---|
| 1195 | /// Is the reference type `ty` shared? | 
|---|
| 1196 | /// | 
|---|
| 1197 | /// This is complicated by concrete heap types whose shared-ness must be | 
|---|
| 1198 | /// checked by looking at the type they point to. | 
|---|
| 1199 | pub fn reftype_is_shared(&self, ty: RefType) -> bool { | 
|---|
| 1200 | match ty.heap_type() { | 
|---|
| 1201 | HeapType::Abstract { shared, .. } => shared, | 
|---|
| 1202 | HeapType::Concrete(index) => { | 
|---|
| 1203 | self[index.as_core_type_id().unwrap()].composite_type.shared | 
|---|
| 1204 | } | 
|---|
| 1205 | } | 
|---|
| 1206 | } | 
|---|
| 1207 |  | 
|---|
| 1208 | /// Get the top type of the given heap type. | 
|---|
| 1209 | /// | 
|---|
| 1210 | /// Concrete types must have had their indices canonicalized to core type | 
|---|
| 1211 | /// ids, otherwise this method will panic. | 
|---|
| 1212 | pub fn top_type(&self, heap_type: &HeapType) -> HeapType { | 
|---|
| 1213 | use AbstractHeapType::*; | 
|---|
| 1214 | match *heap_type { | 
|---|
| 1215 | HeapType::Concrete(idx) => { | 
|---|
| 1216 | let ty = &self[idx.as_core_type_id().unwrap()].composite_type; | 
|---|
| 1217 | let shared = ty.shared; | 
|---|
| 1218 | match ty.inner { | 
|---|
| 1219 | CompositeInnerType::Func(_) => HeapType::Abstract { shared, ty: Func }, | 
|---|
| 1220 | CompositeInnerType::Array(_) | CompositeInnerType::Struct(_) => { | 
|---|
| 1221 | HeapType::Abstract { shared, ty: Any } | 
|---|
| 1222 | } | 
|---|
| 1223 | CompositeInnerType::Cont(_) => HeapType::Abstract { shared, ty: Cont }, | 
|---|
| 1224 | } | 
|---|
| 1225 | } | 
|---|
| 1226 | HeapType::Abstract { shared, ty } => { | 
|---|
| 1227 | let ty = match ty { | 
|---|
| 1228 | Func | NoFunc => Func, | 
|---|
| 1229 | Extern | NoExtern => Extern, | 
|---|
| 1230 | Any | Eq | Struct | Array | I31 | None => Any, | 
|---|
| 1231 | Exn | NoExn => Exn, | 
|---|
| 1232 | Cont | NoCont => Cont, | 
|---|
| 1233 | }; | 
|---|
| 1234 | HeapType::Abstract { shared, ty } | 
|---|
| 1235 | } | 
|---|
| 1236 | } | 
|---|
| 1237 | } | 
|---|
| 1238 |  | 
|---|
| 1239 | pub fn commit(&mut self) -> TypeList { | 
|---|
| 1240 | TypeList { | 
|---|
| 1241 | core_types: self.core_types.commit(), | 
|---|
| 1242 | core_type_to_rec_group: self.core_type_to_rec_group.commit(), | 
|---|
| 1243 | core_type_to_supertype: self.core_type_to_supertype.commit(), | 
|---|
| 1244 | core_type_to_depth: None, | 
|---|
| 1245 | rec_group_elements: self.rec_group_elements.commit(), | 
|---|
| 1246 | canonical_rec_groups: None, | 
|---|
| 1247 | #[ cfg(feature = "component-model")] | 
|---|
| 1248 | component: self.component.commit(), | 
|---|
| 1249 | } | 
|---|
| 1250 | } | 
|---|
| 1251 | } | 
|---|
| 1252 |  | 
|---|
| 1253 | impl<T> Index<T> for TypeList | 
|---|
| 1254 | where | 
|---|
| 1255 | T: TypeIdentifier, | 
|---|
| 1256 | { | 
|---|
| 1257 | type Output = T::Data; | 
|---|
| 1258 |  | 
|---|
| 1259 | fn index(&self, id: T) -> &Self::Output { | 
|---|
| 1260 | let arena: &SnapshotList<::Data> = T::list(self); | 
|---|
| 1261 | &arena[id.index()] | 
|---|
| 1262 | } | 
|---|
| 1263 | } | 
|---|
| 1264 |  | 
|---|
| 1265 | /// Thin wrapper around `TypeList` which provides an allocator of unique ids for | 
|---|
| 1266 | /// types contained within this list. | 
|---|
| 1267 | pub(crate) struct TypeAlloc { | 
|---|
| 1268 | list: TypeList, | 
|---|
| 1269 | #[ cfg(feature = "component-model")] | 
|---|
| 1270 | pub(super) component_alloc: ComponentTypeAlloc, | 
|---|
| 1271 | } | 
|---|
| 1272 |  | 
|---|
| 1273 | impl Default for TypeAlloc { | 
|---|
| 1274 | fn default() -> TypeAlloc { | 
|---|
| 1275 | let mut ret: TypeAlloc = TypeAlloc { | 
|---|
| 1276 | list: TypeList::default(), | 
|---|
| 1277 | #[ cfg(feature = "component-model")] | 
|---|
| 1278 | component_alloc: ComponentTypeAlloc::default(), | 
|---|
| 1279 | }; | 
|---|
| 1280 | ret.list.core_type_to_depth = Some(Default::default()); | 
|---|
| 1281 | ret.list.canonical_rec_groups = Some(Default::default()); | 
|---|
| 1282 | ret | 
|---|
| 1283 | } | 
|---|
| 1284 | } | 
|---|
| 1285 |  | 
|---|
| 1286 | impl Deref for TypeAlloc { | 
|---|
| 1287 | type Target = TypeList; | 
|---|
| 1288 | fn deref(&self) -> &TypeList { | 
|---|
| 1289 | &self.list | 
|---|
| 1290 | } | 
|---|
| 1291 | } | 
|---|
| 1292 |  | 
|---|
| 1293 | impl DerefMut for TypeAlloc { | 
|---|
| 1294 | fn deref_mut(&mut self) -> &mut TypeList { | 
|---|
| 1295 | &mut self.list | 
|---|
| 1296 | } | 
|---|
| 1297 | } | 
|---|
| 1298 |  | 
|---|
| 1299 | impl<T> Index<T> for TypeAlloc | 
|---|
| 1300 | where | 
|---|
| 1301 | T: TypeIdentifier, | 
|---|
| 1302 | { | 
|---|
| 1303 | type Output = T::Data; | 
|---|
| 1304 |  | 
|---|
| 1305 | #[ inline] | 
|---|
| 1306 | fn index(&self, id: T) -> &T::Data { | 
|---|
| 1307 | &self.list[id] | 
|---|
| 1308 | } | 
|---|
| 1309 | } | 
|---|
| 1310 |  | 
|---|