From da4c7e7ed675c3bf405668739c3012d140856109 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:34:42 +0200 Subject: Adding upstream version 126.0. Signed-off-by: Daniel Baumann --- third_party/rust/uniffi_meta/src/ffi_names.rs | 13 ++- third_party/rust/uniffi_meta/src/group.rs | 9 +- third_party/rust/uniffi_meta/src/lib.rs | 65 ++++++----- third_party/rust/uniffi_meta/src/metadata.rs | 13 ++- third_party/rust/uniffi_meta/src/reader.rs | 148 +++++++++++++++++++++----- third_party/rust/uniffi_meta/src/types.rs | 22 ++-- 6 files changed, 190 insertions(+), 80 deletions(-) (limited to 'third_party/rust/uniffi_meta/src') diff --git a/third_party/rust/uniffi_meta/src/ffi_names.rs b/third_party/rust/uniffi_meta/src/ffi_names.rs index 44a5bc3e63..5c931a09e3 100644 --- a/third_party/rust/uniffi_meta/src/ffi_names.rs +++ b/third_party/rust/uniffi_meta/src/ffi_names.rs @@ -33,6 +33,12 @@ pub fn method_symbol_name(namespace: &str, object_name: &str, name: &str) -> Str format!("uniffi_{namespace}_fn_method_{object_name}_{name}") } +/// FFI symbol name for the `clone` function for an object. +pub fn clone_fn_symbol_name(namespace: &str, object_name: &str) -> String { + let object_name = object_name.to_ascii_lowercase(); + format!("uniffi_{namespace}_fn_clone_{object_name}") +} + /// FFI symbol name for the `free` function for an object. pub fn free_fn_symbol_name(namespace: &str, object_name: &str) -> String { let object_name = object_name.to_ascii_lowercase(); @@ -40,9 +46,12 @@ pub fn free_fn_symbol_name(namespace: &str, object_name: &str) -> String { } /// FFI symbol name for the `init_callback` function for a callback interface -pub fn init_callback_fn_symbol_name(namespace: &str, callback_interface_name: &str) -> String { +pub fn init_callback_vtable_fn_symbol_name( + namespace: &str, + callback_interface_name: &str, +) -> String { let callback_interface_name = callback_interface_name.to_ascii_lowercase(); - format!("uniffi_{namespace}_fn_init_callback_{callback_interface_name}") + format!("uniffi_{namespace}_fn_init_callback_vtable_{callback_interface_name}") } /// FFI checksum symbol name for a top-level function diff --git a/third_party/rust/uniffi_meta/src/group.rs b/third_party/rust/uniffi_meta/src/group.rs index f0be2e5a98..a41776bf8a 100644 --- a/third_party/rust/uniffi_meta/src/group.rs +++ b/third_party/rust/uniffi_meta/src/group.rs @@ -18,6 +18,7 @@ pub fn create_metadata_groups(items: &[Metadata]) -> MetadataGroupMap { Metadata::Namespace(namespace) => { let group = MetadataGroup { namespace: namespace.clone(), + namespace_docstring: None, items: BTreeSet::new(), }; Some((namespace.crate_name.clone(), group)) @@ -29,6 +30,7 @@ pub fn create_metadata_groups(items: &[Metadata]) -> MetadataGroupMap { }; let group = MetadataGroup { namespace, + namespace_docstring: None, items: BTreeSet::new(), }; Some((udl.module_path.clone(), group)) @@ -63,6 +65,7 @@ pub fn group_metadata(group_map: &mut MetadataGroupMap, items: Vec) -> #[derive(Debug)] pub struct MetadataGroup { pub namespace: NamespaceMetadata, + pub namespace_docstring: Option, pub items: BTreeSet, } @@ -127,12 +130,6 @@ impl<'a> ExternalTypeConverter<'a> { ..meta }), Metadata::Enum(meta) => Metadata::Enum(self.convert_enum(meta)), - Metadata::Error(meta) => Metadata::Error(match meta { - ErrorMetadata::Enum { enum_, is_flat } => ErrorMetadata::Enum { - enum_: self.convert_enum(enum_), - is_flat, - }, - }), _ => item, } } diff --git a/third_party/rust/uniffi_meta/src/lib.rs b/third_party/rust/uniffi_meta/src/lib.rs index e486d84d89..90f7b2d3cd 100644 --- a/third_party/rust/uniffi_meta/src/lib.rs +++ b/third_party/rust/uniffi_meta/src/lib.rs @@ -23,7 +23,7 @@ mod metadata; // `docs/uniffi-versioning.md` for details. // // Once we get to 1.0, then we'll need to update the scheme to something like 100 + major_version -pub const UNIFFI_CONTRACT_VERSION: u32 = 24; +pub const UNIFFI_CONTRACT_VERSION: u32 = 26; /// Similar to std::hash::Hash. /// @@ -143,6 +143,7 @@ pub struct FnMetadata { pub return_type: Option, pub throws: Option, pub checksum: Option, + pub docstring: Option, } impl FnMetadata { @@ -160,9 +161,11 @@ pub struct ConstructorMetadata { pub module_path: String, pub self_name: String, pub name: String, + pub is_async: bool, pub inputs: Vec, pub throws: Option, pub checksum: Option, + pub docstring: Option, } impl ConstructorMetadata { @@ -190,6 +193,7 @@ pub struct MethodMetadata { pub throws: Option, pub takes_self_by_arc: bool, // unused except by rust udl bindgen. pub checksum: Option, + pub docstring: Option, } impl MethodMetadata { @@ -216,6 +220,7 @@ pub struct TraitMethodMetadata { pub throws: Option, pub takes_self_by_arc: bool, // unused except by rust udl bindgen. pub checksum: Option, + pub docstring: Option, } impl TraitMethodMetadata { @@ -266,7 +271,17 @@ pub enum LiteralMetadata { Enum(String, Type), EmptySequence, EmptyMap, - Null, + None, + Some { inner: Box }, +} + +impl LiteralMetadata { + pub fn new_uint(v: u64) -> Self { + LiteralMetadata::UInt(v, Radix::Decimal, Type::UInt64) + } + pub fn new_int(v: i64) -> Self { + LiteralMetadata::Int(v, Radix::Decimal, Type::Int64) + } } // Represent the radix of integer literal values. @@ -283,6 +298,7 @@ pub struct RecordMetadata { pub module_path: String, pub name: String, pub fields: Vec, + pub docstring: Option, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -290,19 +306,26 @@ pub struct FieldMetadata { pub name: String, pub ty: Type, pub default: Option, + pub docstring: Option, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct EnumMetadata { pub module_path: String, pub name: String, + pub forced_flatness: Option, pub variants: Vec, + pub discr_type: Option, + pub non_exhaustive: bool, + pub docstring: Option, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct VariantMetadata { pub name: String, + pub discr: Option, pub fields: Vec, + pub docstring: Option, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -310,15 +333,25 @@ pub struct ObjectMetadata { pub module_path: String, pub name: String, pub imp: types::ObjectImpl, + pub docstring: Option, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct CallbackInterfaceMetadata { pub module_path: String, pub name: String, + pub docstring: Option, } impl ObjectMetadata { + /// FFI symbol name for the `clone` function for this object. + /// + /// This function is used to increment the reference count before lowering an object to pass + /// back to Rust. + pub fn clone_ffi_symbol_name(&self) -> String { + clone_fn_symbol_name(&self.module_path, &self.name) + } + /// FFI symbol name for the `free` function for this object. /// /// This function is used to free the memory used by this object. @@ -368,6 +401,7 @@ impl UniffiTraitMetadata { } #[repr(u8)] +#[derive(Eq, PartialEq, Hash)] pub enum UniffiTraitDiscriminants { Debug, Display, @@ -387,25 +421,6 @@ impl UniffiTraitDiscriminants { } } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum ErrorMetadata { - Enum { enum_: EnumMetadata, is_flat: bool }, -} - -impl ErrorMetadata { - pub fn name(&self) -> &String { - match self { - Self::Enum { enum_, .. } => &enum_.name, - } - } - - pub fn module_path(&self) -> &String { - match self { - Self::Enum { enum_, .. } => &enum_.module_path, - } - } -} - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct CustomTypeMetadata { pub module_path: String, @@ -433,7 +448,6 @@ pub enum Metadata { CallbackInterface(CallbackInterfaceMetadata), Record(RecordMetadata), Enum(EnumMetadata), - Error(ErrorMetadata), Constructor(ConstructorMetadata), Method(MethodMetadata), TraitMethod(TraitMethodMetadata), @@ -458,7 +472,6 @@ impl Metadata { Metadata::Object(meta) => &meta.module_path, Metadata::CallbackInterface(meta) => &meta.module_path, Metadata::TraitMethod(meta) => &meta.module_path, - Metadata::Error(meta) => meta.module_path(), Metadata::CustomType(meta) => &meta.module_path, Metadata::UniffiTrait(meta) => meta.module_path(), } @@ -507,12 +520,6 @@ impl From for Metadata { } } -impl From for Metadata { - fn from(e: ErrorMetadata) -> Self { - Self::Error(e) - } -} - impl From for Metadata { fn from(v: ObjectMetadata) -> Self { Self::Object(v) diff --git a/third_party/rust/uniffi_meta/src/metadata.rs b/third_party/rust/uniffi_meta/src/metadata.rs index 6e490a4866..9cfb77a244 100644 --- a/third_party/rust/uniffi_meta/src/metadata.rs +++ b/third_party/rust/uniffi_meta/src/metadata.rs @@ -7,7 +7,7 @@ // `uniffi_core`. // This is the easy way out of that issue and is a temporary hacky solution. -/// Metadata constants, make sure to keep this in sync with copy in `uniffi_meta::reader` +/// Metadata constants, make sure to keep this in sync with copy in `uniffi_core::metadata` pub mod codes { // Top-level metadata item codes pub const FUNC: u8 = 0; @@ -15,13 +15,14 @@ pub mod codes { pub const RECORD: u8 = 2; pub const ENUM: u8 = 3; pub const INTERFACE: u8 = 4; - pub const ERROR: u8 = 5; pub const NAMESPACE: u8 = 6; pub const CONSTRUCTOR: u8 = 7; pub const UDL_FILE: u8 = 8; pub const CALLBACK_INTERFACE: u8 = 9; pub const TRAIT_METHOD: u8 = 10; pub const UNIFFI_TRAIT: u8 = 11; + pub const TRAIT_INTERFACE: u8 = 12; + pub const CALLBACK_TRAIT_INTERFACE: u8 = 13; //pub const UNKNOWN: u8 = 255; // Type codes @@ -49,8 +50,8 @@ pub mod codes { pub const TYPE_CALLBACK_INTERFACE: u8 = 21; pub const TYPE_CUSTOM: u8 = 22; pub const TYPE_RESULT: u8 = 23; - //pub const TYPE_FUTURE: u8 = 24; - pub const TYPE_FOREIGN_EXECUTOR: u8 = 25; + pub const TYPE_TRAIT_INTERFACE: u8 = 24; + pub const TYPE_CALLBACK_TRAIT_INTERFACE: u8 = 25; pub const TYPE_UNIT: u8 = 255; // Literal codes @@ -58,7 +59,9 @@ pub mod codes { pub const LIT_INT: u8 = 1; pub const LIT_FLOAT: u8 = 2; pub const LIT_BOOL: u8 = 3; - pub const LIT_NULL: u8 = 4; + pub const LIT_NONE: u8 = 4; + pub const LIT_SOME: u8 = 5; + pub const LIT_EMPTY_SEQ: u8 = 6; } // Create a checksum for a MetadataBuffer diff --git a/third_party/rust/uniffi_meta/src/reader.rs b/third_party/rust/uniffi_meta/src/reader.rs index bf6525f2b5..6fec6cb3a3 100644 --- a/third_party/rust/uniffi_meta/src/reader.rs +++ b/third_party/rust/uniffi_meta/src/reader.rs @@ -52,9 +52,10 @@ impl<'a> MetadataReader<'a> { codes::CONSTRUCTOR => self.read_constructor()?.into(), codes::METHOD => self.read_method()?.into(), codes::RECORD => self.read_record()?.into(), - codes::ENUM => self.read_enum(false)?.into(), - codes::ERROR => self.read_error()?.into(), - codes::INTERFACE => self.read_object()?.into(), + codes::ENUM => self.read_enum()?.into(), + codes::INTERFACE => self.read_object(ObjectImpl::Struct)?.into(), + codes::TRAIT_INTERFACE => self.read_object(ObjectImpl::Trait)?.into(), + codes::CALLBACK_TRAIT_INTERFACE => self.read_object(ObjectImpl::CallbackTrait)?.into(), codes::CALLBACK_INTERFACE => self.read_callback_interface()?.into(), codes::TRAIT_METHOD => self.read_trait_method()?.into(), codes::UNIFFI_TRAIT => self.read_uniffi_trait()?.into(), @@ -80,6 +81,17 @@ impl<'a> MetadataReader<'a> { } } + fn read_u16(&mut self) -> Result { + if self.buf.len() >= 2 { + // read the value as little-endian + let value = u16::from_le_bytes([self.buf[0], self.buf[1]]); + self.buf = &self.buf[2..]; + Ok(value) + } else { + bail!("Not enough data left in buffer to read a u16 value"); + } + } + fn read_u32(&mut self) -> Result { if self.buf.len() >= 4 { // read the value as little-endian @@ -105,6 +117,17 @@ impl<'a> MetadataReader<'a> { String::from_utf8(slice.into()).context("Invalid string data") } + fn read_long_string(&mut self) -> Result { + let size = self.read_u16()? as usize; + let slice; + (slice, self.buf) = self.buf.split_at(size); + String::from_utf8(slice.into()).context("Invalid string data") + } + + fn read_optional_long_string(&mut self) -> Result> { + Ok(Some(self.read_long_string()?).filter(|str| !str.is_empty())) + } + fn read_type(&mut self) -> Result { let value = self.read_u8()?; Ok(match value { @@ -122,7 +145,6 @@ impl<'a> MetadataReader<'a> { codes::TYPE_STRING => Type::String, codes::TYPE_DURATION => Type::Duration, codes::TYPE_SYSTEM_TIME => Type::Timestamp, - codes::TYPE_FOREIGN_EXECUTOR => Type::ForeignExecutor, codes::TYPE_RECORD => Type::Record { module_path: self.read_string()?, name: self.read_string()?, @@ -134,7 +156,17 @@ impl<'a> MetadataReader<'a> { codes::TYPE_INTERFACE => Type::Object { module_path: self.read_string()?, name: self.read_string()?, - imp: ObjectImpl::from_is_trait(self.read_bool()?), + imp: ObjectImpl::Struct, + }, + codes::TYPE_TRAIT_INTERFACE => Type::Object { + module_path: self.read_string()?, + name: self.read_string()?, + imp: ObjectImpl::Trait, + }, + codes::TYPE_CALLBACK_TRAIT_INTERFACE => Type::Object { + module_path: self.read_string()?, + name: self.read_string()?, + imp: ObjectImpl::CallbackTrait, }, codes::TYPE_CALLBACK_INTERFACE => Type::CallbackInterface { module_path: self.read_string()?, @@ -198,6 +230,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(FnMetadata { module_path, name, @@ -205,6 +238,7 @@ impl<'a> MetadataReader<'a> { inputs, return_type, throws, + docstring, checksum: self.calc_checksum(), }) } @@ -213,8 +247,10 @@ impl<'a> MetadataReader<'a> { let module_path = self.read_string()?; let self_name = self.read_string()?; let name = self.read_string()?; + let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; return_type .filter(|t| { @@ -228,10 +264,12 @@ impl<'a> MetadataReader<'a> { Ok(ConstructorMetadata { module_path, self_name, + is_async, name, inputs, throws, checksum: self.calc_checksum(), + docstring, }) } @@ -242,6 +280,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(MethodMetadata { module_path, self_name, @@ -252,6 +291,7 @@ impl<'a> MetadataReader<'a> { throws, takes_self_by_arc: false, // not emitted by macros checksum: self.calc_checksum(), + docstring, }) } @@ -260,13 +300,25 @@ impl<'a> MetadataReader<'a> { module_path: self.read_string()?, name: self.read_string()?, fields: self.read_fields()?, + docstring: self.read_optional_long_string()?, }) } - fn read_enum(&mut self, is_flat_error: bool) -> Result { + fn read_enum(&mut self) -> Result { let module_path = self.read_string()?; let name = self.read_string()?; - let variants = if is_flat_error { + let forced_flatness = match self.read_u8()? { + 0 => None, + 1 => Some(false), + 2 => Some(true), + _ => unreachable!("invalid flatness"), + }; + let discr_type = if self.read_bool()? { + Some(self.read_type()?) + } else { + None + }; + let variants = if forced_flatness == Some(true) { self.read_flat_variants()? } else { self.read_variants()? @@ -275,21 +327,20 @@ impl<'a> MetadataReader<'a> { Ok(EnumMetadata { module_path, name, + forced_flatness, + discr_type, variants, + non_exhaustive: self.read_bool()?, + docstring: self.read_optional_long_string()?, }) } - fn read_error(&mut self) -> Result { - let is_flat = self.read_bool()?; - let enum_ = self.read_enum(is_flat)?; - Ok(ErrorMetadata::Enum { enum_, is_flat }) - } - - fn read_object(&mut self) -> Result { + fn read_object(&mut self, imp: ObjectImpl) -> Result { Ok(ObjectMetadata { module_path: self.read_string()?, name: self.read_string()?, - imp: ObjectImpl::from_is_trait(self.read_bool()?), + imp, + docstring: self.read_optional_long_string()?, }) } @@ -322,6 +373,7 @@ impl<'a> MetadataReader<'a> { Ok(CallbackInterfaceMetadata { module_path: self.read_string()?, name: self.read_string()?, + docstring: self.read_optional_long_string()?, }) } @@ -333,6 +385,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(TraitMethodMetadata { module_path, trait_name, @@ -344,6 +397,7 @@ impl<'a> MetadataReader<'a> { throws, takes_self_by_arc: false, // not emitted by macros checksum: self.calc_checksum(), + docstring, }) } @@ -353,8 +407,13 @@ impl<'a> MetadataReader<'a> { .map(|_| { let name = self.read_string()?; let ty = self.read_type()?; - let default = self.read_default(&name, &ty)?; - Ok(FieldMetadata { name, ty, default }) + let default = self.read_optional_default(&name, &ty)?; + Ok(FieldMetadata { + name, + ty, + default, + docstring: self.read_optional_long_string()?, + }) }) .collect() } @@ -365,7 +424,9 @@ impl<'a> MetadataReader<'a> { .map(|_| { Ok(VariantMetadata { name: self.read_string()?, + discr: self.read_optional_default("", &Type::UInt64)?, fields: self.read_fields()?, + docstring: self.read_optional_long_string()?, }) }) .collect() @@ -377,7 +438,9 @@ impl<'a> MetadataReader<'a> { .map(|_| { Ok(VariantMetadata { name: self.read_string()?, + discr: None, fields: vec![], + docstring: self.read_optional_long_string()?, }) }) .collect() @@ -387,13 +450,16 @@ impl<'a> MetadataReader<'a> { let len = self.read_u8()?; (0..len) .map(|_| { + let name = self.read_string()?; + let ty = self.read_type()?; + let default = self.read_optional_default(&name, &ty)?; Ok(FnParamMetadata { - name: self.read_string()?, - ty: self.read_type()?, + name, + ty, + default, // not emitted by macros by_ref: false, optional: false, - default: None, }) }) .collect() @@ -405,14 +471,18 @@ impl<'a> MetadataReader<'a> { Some(checksum_metadata(metadata_buf)) } - fn read_default(&mut self, name: &str, ty: &Type) -> Result> { - let has_default = self.read_bool()?; - if !has_default { - return Ok(None); + fn read_optional_default(&mut self, name: &str, ty: &Type) -> Result> { + if self.read_bool()? { + Ok(Some(self.read_default(name, ty)?)) + } else { + Ok(None) } + } + fn read_default(&mut self, name: &str, ty: &Type) -> Result { let literal_kind = self.read_u8()?; - Ok(Some(match literal_kind { + + Ok(match literal_kind { codes::LIT_STR => { ensure!( matches!(ty, Type::String), @@ -422,12 +492,24 @@ impl<'a> MetadataReader<'a> { } codes::LIT_INT => { let base10_digits = self.read_string()?; + // procmacros emit the type for discriminant values based purely on whether the constant + // is positive or negative. + let ty = if !base10_digits.is_empty() + && base10_digits.as_bytes()[0] == b'-' + && ty == &Type::UInt64 + { + &Type::Int64 + } else { + ty + }; macro_rules! parse_int { ($ty:ident, $variant:ident) => { LiteralMetadata::$variant( base10_digits .parse::<$ty>() - .with_context(|| format!("parsing default for field {name}"))? + .with_context(|| { + format!("parsing default for field {name}: {base10_digits}") + })? .into(), Radix::Decimal, ty.to_owned(), @@ -458,8 +540,18 @@ impl<'a> MetadataReader<'a> { } }, codes::LIT_BOOL => LiteralMetadata::Boolean(self.read_bool()?), - codes::LIT_NULL => LiteralMetadata::Null, + codes::LIT_NONE => match ty { + Type::Optional { .. } => LiteralMetadata::None, + _ => bail!("field {name} of type {ty:?} can't have a default value of None"), + }, + codes::LIT_SOME => match ty { + Type::Optional { inner_type, .. } => LiteralMetadata::Some { + inner: Box::new(self.read_default(name, inner_type)?), + }, + _ => bail!("field {name} of type {ty:?} can't have a default value of None"), + }, + codes::LIT_EMPTY_SEQ => LiteralMetadata::EmptySequence, _ => bail!("Unexpected literal kind code: {literal_kind:?}"), - })) + }) } } diff --git a/third_party/rust/uniffi_meta/src/types.rs b/third_party/rust/uniffi_meta/src/types.rs index 24f8a6f2a8..51bf156b50 100644 --- a/third_party/rust/uniffi_meta/src/types.rs +++ b/third_party/rust/uniffi_meta/src/types.rs @@ -21,8 +21,12 @@ use crate::Checksum; #[derive(Debug, Copy, Clone, Eq, PartialEq, Checksum, Ord, PartialOrd)] pub enum ObjectImpl { + // A single Rust type Struct, + // A trait that's can be implemented by Rust types Trait, + // A trait + a callback interface -- can be implemented by both Rust and foreign types. + CallbackTrait, } impl ObjectImpl { @@ -31,27 +35,26 @@ impl ObjectImpl { /// Includes `r#`, traits get a leading `dyn`. If we ever supported associated types, then /// this would also include them. pub fn rust_name_for(&self, name: &str) -> String { - if self == &ObjectImpl::Trait { + if self.is_trait_interface() { format!("dyn r#{name}") } else { format!("r#{name}") } } - // uniffi_meta and procmacro support tend to carry around `is_trait` bools. This makes that - // mildly less painful - pub fn from_is_trait(is_trait: bool) -> Self { - if is_trait { - ObjectImpl::Trait - } else { - ObjectImpl::Struct - } + pub fn is_trait_interface(&self) -> bool { + matches!(self, Self::Trait | Self::CallbackTrait) + } + + pub fn has_callback_interface(&self) -> bool { + matches!(self, Self::CallbackTrait) } } #[derive(Debug, Clone, Copy, Eq, PartialEq, Checksum, Ord, PartialOrd)] pub enum ExternalKind { Interface, + Trait, // Either a record or enum DataClass, } @@ -85,7 +88,6 @@ pub enum Type { // How the object is implemented. imp: ObjectImpl, }, - ForeignExecutor, // Types defined in the component API, each of which has a string name. Record { module_path: String, -- cgit v1.2.3