diff --git a/crates/rune-macros/src/context.rs b/crates/rune-macros/src/context.rs index cb9f2f6e5..ba99eee3a 100644 --- a/crates/rune-macros/src/context.rs +++ b/crates/rune-macros/src/context.rs @@ -775,7 +775,6 @@ impl Context { value_mut_guard: path(m, ["runtime", "ValueMutGuard"]), value_ref_guard: path(m, ["runtime", "ValueRefGuard"]), value: path(m, ["runtime", "Value"]), - variant_data: path(m, ["runtime", "VariantData"]), vec: path(m, ["alloc", "Vec"]), vm_result: path(m, ["runtime", "VmResult"]), vm_try: path(m, ["vm_try"]), @@ -870,7 +869,6 @@ pub(crate) struct Tokens { pub(crate) value_mut_guard: syn::Path, pub(crate) value_ref_guard: syn::Path, pub(crate) value: syn::Path, - pub(crate) variant_data: syn::Path, pub(crate) vec: syn::Path, pub(crate) vm_result: syn::Path, pub(crate) vm_try: syn::Path, diff --git a/crates/rune-macros/src/from_value.rs b/crates/rune-macros/src/from_value.rs index 007d2f109..34d88ff00 100644 --- a/crates/rune-macros/src/from_value.rs +++ b/crates/rune-macros/src/from_value.rs @@ -104,7 +104,6 @@ impl Expander<'_> { let Tokens { type_value, from_value, - variant_data, value, result, runtime_error, @@ -145,27 +144,37 @@ impl Expander<'_> { }; let variant = quote! { - #type_value::Variant(variant) => { - let mut it = variant.rtti().item.iter(); + #type_value::EmptyStruct(data) => { + let mut it = data.rtti().item.iter(); let Some(name) = it.next_back_str() else { return #result::Err(#runtime_error::__rune_macros__missing_variant_name()); }; - match variant.data() { - #variant_data::Empty => match name { - #(#unit_matches,)* #missing, - }, - #variant_data::Tuple(tuple) => match name { - #(#unnamed_matches,)* #missing, - }, - #variant_data::Struct(data) => { - let object = variant.accessor(data); - - match name { - #(#named_matches,)* #missing, - } - } + match name { + #(#unit_matches,)* #missing, + } + } + #type_value::TupleStruct(tuple) => { + let mut it = tuple.rtti().item.iter(); + + let Some(name) = it.next_back_str() else { + return #result::Err(#runtime_error::__rune_macros__missing_variant_name()); + }; + + match name { + #(#unnamed_matches,)* #missing, + } + } + #type_value::Struct(object) => { + let mut it = object.rtti().item.iter(); + + let Some(name) = it.next_back_str() else { + return #result::Err(#runtime_error::__rune_macros__missing_variant_name()); + }; + + match name { + #(#named_matches,)* #missing, } } }; diff --git a/crates/rune/src/compile/context.rs b/crates/rune/src/compile/context.rs index bd6fa40d7..e46f219e1 100644 --- a/crates/rune/src/compile/context.rs +++ b/crates/rune/src/compile/context.rs @@ -771,7 +771,7 @@ impl Context { item: item.try_clone()?, hash, type_check: None, - type_info: TypeInfo::typed(Arc::new(Rtti { + type_info: TypeInfo::rtti(Arc::new(Rtti { hash: ty.hash, variant_hash: hash, item: item.try_clone()?, diff --git a/crates/rune/src/compile/unit_builder.rs b/crates/rune/src/compile/unit_builder.rs index 6dc0381a0..6e03e6e6d 100644 --- a/crates/rune/src/compile/unit_builder.rs +++ b/crates/rune/src/compile/unit_builder.rs @@ -496,7 +496,7 @@ impl UnitBuilder { )); } - let info = UnitFn::UnitVariant { hash: meta.hash }; + let info = UnitFn::EmptyStruct { hash: meta.hash }; let signature = DebugSignature::new( pool.item(meta.item_meta.item).try_to_owned()?, @@ -545,7 +545,7 @@ impl UnitBuilder { )); } - let info = UnitFn::TupleVariant { + let info = UnitFn::TupleStruct { hash: meta.hash, args, }; diff --git a/crates/rune/src/compile/v1/assemble.rs b/crates/rune/src/compile/v1/assemble.rs index e1e13c6a1..733865f3e 100644 --- a/crates/rune/src/compile/v1/assemble.rs +++ b/crates/rune/src/compile/v1/assemble.rs @@ -2527,7 +2527,7 @@ fn expr_object<'a, 'hir>( span, )?; } - hir::ExprObjectKind::Struct { hash } => { + hir::ExprObjectKind::Struct { hash } | hir::ExprObjectKind::StructVariant { hash } => { cx.asm.push( Inst::Struct { addr: linear.addr(), @@ -2537,16 +2537,6 @@ fn expr_object<'a, 'hir>( span, )?; } - hir::ExprObjectKind::StructVariant { hash } => { - cx.asm.push( - Inst::StructVariant { - addr: linear.addr(), - hash, - out: needs.alloc_output()?, - }, - span, - )?; - } hir::ExprObjectKind::ExternalType { hash, args } => { reorder_field_assignments(cx, hir, linear.addr(), span)?; diff --git a/crates/rune/src/runtime/function.rs b/crates/rune/src/runtime/function.rs index 6fdcb1796..b08f6f927 100644 --- a/crates/rune/src/runtime/function.rs +++ b/crates/rune/src/runtime/function.rs @@ -16,8 +16,8 @@ use crate::Hash; use super::{ Args, Call, ConstValue, Formatter, FromValue, FunctionHandler, GuardedArgs, InstAddress, - Output, OwnedTuple, Rtti, RuntimeContext, RuntimeError, Stack, Unit, Value, Vm, VmCall, - VmErrorKind, VmHalt, VmResult, + Output, OwnedTuple, Rtti, RuntimeContext, RuntimeError, Stack, TupleStruct, Unit, Value, Vm, + VmCall, VmErrorKind, VmHalt, VmResult, }; /// The type of a function in Rune. @@ -255,16 +255,6 @@ impl Function { Self(FunctionImpl::from_tuple_struct(rtti, args)) } - /// Create a function pointer that constructs a empty variant. - pub(crate) fn from_unit_variant(rtti: Arc) -> Self { - Self(FunctionImpl::from_unit_variant(rtti)) - } - - /// Create a function pointer that constructs a tuple variant. - pub(crate) fn from_tuple_variant(rtti: Arc, args: usize) -> Self { - Self(FunctionImpl::from_tuple_variant(rtti, args)) - } - /// Type [Hash][struct@Hash] of the underlying function. /// /// # Examples @@ -581,16 +571,6 @@ where let (args, _guard) = vm_try!(unsafe { args.guarded_into_vec() }); vm_try!(Value::tuple_struct(tuple.rtti.clone(), args)) } - Inner::FnUnitVariant(unit) => { - vm_try!(check_args(args.count(), 0)); - vm_try!(Value::unit_variant(unit.rtti.clone())) - } - Inner::FnTupleVariant(tuple) => { - vm_try!(check_args(args.count(), tuple.args)); - // SAFETY: We don't let the guard outlive the value. - let (args, _guard) = vm_try!(unsafe { args.guarded_into_vec() }); - vm_try!(Value::tuple_variant(tuple.rtti.clone(), args)) - } }; VmResult::Ok(vm_try!(T::from_value(value))) @@ -667,30 +647,13 @@ where vm_try!(check_args(args, tuple.args)); let seq = vm_try!(vm.stack().slice_at(addr, args)); - let seq = vm_try!(seq.iter().cloned().try_collect()); + let data = vm_try!(seq.iter().cloned().try_collect()); - vm_try!(out.store(vm.stack_mut(), || { - Value::tuple_struct(tuple.rtti.clone(), seq) + vm_try!(out.store(vm.stack_mut(), || TupleStruct { + rtti: tuple.rtti.clone(), + data })); - None - } - Inner::FnUnitVariant(tuple) => { - vm_try!(check_args(args, 0)); - vm_try!(out.store(vm.stack_mut(), || Value::unit_variant(tuple.rtti.clone()))); - None - } - Inner::FnTupleVariant(tuple) => { - vm_try!(check_args(args, tuple.args)); - - let seq = vm_try!(vm.stack().slice_at(addr, args)); - let seq = vm_try!(seq.iter().cloned().try_collect()); - - vm_try!(out.store(vm.stack_mut(), || Value::tuple_variant( - tuple.rtti.clone(), - seq - ))); - None } }; @@ -765,20 +728,6 @@ where } } - /// Create a function pointer that constructs a empty variant. - pub(crate) fn from_unit_variant(rtti: Arc) -> Self { - Self { - inner: Inner::FnUnitVariant(FnUnitVariant { rtti }), - } - } - - /// Create a function pointer that constructs a tuple variant. - pub(crate) fn from_tuple_variant(rtti: Arc, args: usize) -> Self { - Self { - inner: Inner::FnTupleVariant(FnTupleVariant { rtti, args }), - } - } - #[inline] fn type_hash(&self) -> Hash { match &self.inner { @@ -786,10 +735,8 @@ where *hash } Inner::FnClosureOffset(fco) => fco.fn_offset.hash, - Inner::FnUnitStruct(func) => func.rtti.hash, - Inner::FnTupleStruct(func) => func.rtti.hash, - Inner::FnUnitVariant(func) => func.rtti.hash, - Inner::FnTupleVariant(func) => func.rtti.hash, + Inner::FnUnitStruct(func) => func.rtti.type_hash(), + Inner::FnTupleStruct(func) => func.rtti.type_hash(), } } } @@ -814,8 +761,6 @@ impl FunctionImpl { Inner::FnOffset(inner) => Inner::FnOffset(inner), Inner::FnUnitStruct(inner) => Inner::FnUnitStruct(inner), Inner::FnTupleStruct(inner) => Inner::FnTupleStruct(inner), - Inner::FnUnitVariant(inner) => Inner::FnUnitVariant(inner), - Inner::FnTupleVariant(inner) => Inner::FnTupleVariant(inner), }; Ok(FunctionImpl { inner }) @@ -844,12 +789,6 @@ impl fmt::Debug for Function { Inner::FnTupleStruct(tuple) => { write!(f, "tuple {}", tuple.rtti.item)?; } - Inner::FnUnitVariant(empty) => { - write!(f, "variant empty {}", empty.rtti.item)?; - } - Inner::FnTupleVariant(tuple) => { - write!(f, "variant tuple {}", tuple.rtti.item)?; - } } Ok(()) @@ -875,10 +814,6 @@ enum Inner { FnUnitStruct(FnUnitStruct), /// Constructor for a tuple. FnTupleStruct(FnTupleStruct), - /// Constructor for an empty variant. - FnUnitVariant(FnUnitVariant), - /// Constructor for a tuple variant. - FnTupleVariant(FnTupleVariant), } impl TryClone for Inner @@ -892,8 +827,6 @@ where Inner::FnClosureOffset(inner) => Inner::FnClosureOffset(inner.try_clone()?), Inner::FnUnitStruct(inner) => Inner::FnUnitStruct(inner.clone()), Inner::FnTupleStruct(inner) => Inner::FnTupleStruct(inner.clone()), - Inner::FnUnitVariant(inner) => Inner::FnUnitVariant(inner.clone()), - Inner::FnTupleVariant(inner) => Inner::FnTupleVariant(inner.clone()), }) } } @@ -1029,20 +962,6 @@ struct FnTupleStruct { args: usize, } -#[derive(Debug, Clone, TryClone)] -struct FnUnitVariant { - /// Runtime information fo variant. - rtti: Arc, -} - -#[derive(Debug, Clone, TryClone)] -struct FnTupleVariant { - /// Runtime information fo variant. - rtti: Arc, - /// The number of arguments the tuple takes. - args: usize, -} - impl FromValue for SyncFunction { #[inline] fn from_value(value: Value) -> Result { diff --git a/crates/rune/src/runtime/inst.rs b/crates/rune/src/runtime/inst.rs index 1af7bbbe7..8eda20ea2 100644 --- a/crates/rune/src/runtime/inst.rs +++ b/crates/rune/src/runtime/inst.rs @@ -664,27 +664,6 @@ pub enum Inst { /// Where to write the constructed struct. out: Output, }, - /// Construct a push an object variant of the given type onto the stack. The - /// number of elements in the object are determined the slot of the object - /// keys `slot` and are popped from the stack. - /// - /// For each element, a value is popped corresponding to the object key. - /// - /// # Operation - /// - /// ```text - /// - /// => - /// ``` - #[musli(packed)] - StructVariant { - /// The address to load fields from. - addr: InstAddress, - /// The type hash of the object variant to construct. - hash: Hash, - /// Where to write the constructed variant. - out: Output, - }, /// Load a literal string from a static string slot. /// /// # Operation diff --git a/crates/rune/src/runtime/mod.rs b/crates/rune/src/runtime/mod.rs index e8e50155e..b6e574f11 100644 --- a/crates/rune/src/runtime/mod.rs +++ b/crates/rune/src/runtime/mod.rs @@ -165,10 +165,7 @@ pub use self::value::{ Accessor, EmptyStruct, Inline, RawValueGuard, Rtti, Struct, TupleStruct, TypeValue, Value, ValueMutGuard, ValueRefGuard, }; -pub(crate) use self::value::{Mutable, ReprMut, ReprOwned, ReprRef}; - -mod variant; -pub use self::variant::{Variant, VariantData}; +pub(crate) use self::value::{Mutable, ReprMut, ReprRef}; pub mod slice; diff --git a/crates/rune/src/runtime/stack.rs b/crates/rune/src/runtime/stack.rs index fcc070391..3675267c0 100644 --- a/crates/rune/src/runtime/stack.rs +++ b/crates/rune/src/runtime/stack.rs @@ -609,6 +609,7 @@ impl TryClone for Stack { } impl TryFromIteratorIn for Stack { + #[inline] fn try_from_iter_in>( iter: T, alloc: Global, diff --git a/crates/rune/src/runtime/tuple.rs b/crates/rune/src/runtime/tuple.rs index 81ae1745c..0337c683c 100644 --- a/crates/rune/src/runtime/tuple.rs +++ b/crates/rune/src/runtime/tuple.rs @@ -8,6 +8,7 @@ use crate::alloc::alloc::Global; use crate::alloc::borrow::TryToOwned; use crate::alloc::clone::TryClone; use crate::alloc::fmt::TryWrite; +use crate::alloc::iter::{IteratorExt, TryFromIteratorIn}; use crate::alloc::{self, Box}; use crate::Any; @@ -345,6 +346,18 @@ impl TryFrom<::rust_alloc::boxed::Box<[ConstValue]>> for OwnedTuple { } } +impl TryFromIteratorIn for OwnedTuple { + #[inline] + fn try_from_iter_in>( + iter: T, + alloc: Global, + ) -> alloc::Result { + Ok(Self { + inner: iter.into_iter().try_collect_in(alloc)?, + }) + } +} + macro_rules! impl_tuple { // Skip conflicting implementation with `()`. (0) => { diff --git a/crates/rune/src/runtime/type_info.rs b/crates/rune/src/runtime/type_info.rs index ae32a2cbe..122da15c8 100644 --- a/crates/rune/src/runtime/type_info.rs +++ b/crates/rune/src/runtime/type_info.rs @@ -64,7 +64,7 @@ impl TypeInfo { } #[inline] - pub(crate) const fn typed(rtti: Arc) -> Self { + pub(crate) const fn rtti(rtti: Arc) -> Self { Self::new(TypeInfoKind::Runtime(rtti)) } @@ -72,7 +72,7 @@ impl TypeInfo { pub(crate) fn type_hash(&self) -> Hash { match &self.kind { TypeInfoKind::Any(ty) => ty.hash, - TypeInfoKind::Runtime(ty) => ty.hash, + TypeInfoKind::Runtime(ty) => ty.type_hash(), } } } diff --git a/crates/rune/src/runtime/unit.rs b/crates/rune/src/runtime/unit.rs index 2f46400d6..ff94cf6a8 100644 --- a/crates/rune/src/runtime/unit.rs +++ b/crates/rune/src/runtime/unit.rs @@ -76,6 +76,7 @@ pub struct Logic { impl Unit { /// Constructs a new unit from a pair of data and debug info. + #[inline] pub fn from_parts(data: Logic, debug: Option) -> alloc::Result { Ok(Self { logic: data, @@ -85,6 +86,7 @@ impl Unit { /// Construct a new unit with the given content. #[allow(clippy::too_many_arguments)] + #[inline] pub(crate) fn new( storage: S, functions: hash::Map, @@ -110,35 +112,40 @@ impl Unit { } /// Access unit data. + #[inline] pub fn logic(&self) -> &Logic { &self.logic } /// Access debug information for the given location if it is available. + #[inline] pub fn debug_info(&self) -> Option<&DebugInfo> { - let debug = self.debug.as_ref()?; - Some(&**debug) + Some(&**self.debug.as_ref()?) } /// Get raw underlying instructions storage. + #[inline] pub(crate) fn instructions(&self) -> &S { &self.logic.storage } /// Iterate over all static strings in the unit. #[cfg(feature = "cli")] + #[inline] pub(crate) fn iter_static_strings(&self) -> impl Iterator> + '_ { self.logic.static_strings.iter() } /// Iterate over all constants in the unit. #[cfg(feature = "cli")] + #[inline] pub(crate) fn iter_constants(&self) -> impl Iterator + '_ { self.logic.constants.iter() } /// Iterate over all static object keys in the unit. #[cfg(feature = "cli")] + #[inline] pub(crate) fn iter_static_object_keys(&self) -> impl Iterator + '_ { use core::iter; @@ -152,11 +159,13 @@ impl Unit { /// Iterate over dynamic functions. #[cfg(feature = "cli")] + #[inline] pub(crate) fn iter_functions(&self) -> impl Iterator + '_ { self.logic.functions.iter().map(|(h, f)| (*h, f)) } /// Lookup the static string by slot, if it exists. + #[inline] pub(crate) fn lookup_string(&self, slot: usize) -> Result<&Arc, VmError> { Ok(self .logic @@ -166,6 +175,7 @@ impl Unit { } /// Lookup the static byte string by slot, if it exists. + #[inline] pub(crate) fn lookup_bytes(&self, slot: usize) -> Result<&[u8], VmError> { Ok(self .logic @@ -176,6 +186,7 @@ impl Unit { } /// Lookup the static object keys by slot, if it exists. + #[inline] pub(crate) fn lookup_object_keys(&self, slot: usize) -> Option<&[String]> { self.logic .static_object_keys @@ -184,16 +195,19 @@ impl Unit { } /// Lookup run-time information for the given type hash. + #[inline] pub(crate) fn lookup_rtti(&self, hash: Hash) -> Option<&Arc> { self.logic.rtti.get(&hash) } /// Lookup a function in the unit. + #[inline] pub(crate) fn function(&self, hash: Hash) -> Option { self.logic.functions.get(&hash).copied() } /// Lookup a constant from the unit. + #[inline] pub(crate) fn constant(&self, hash: Hash) -> Option<&ConstValue> { self.logic.constants.get(&hash) } @@ -209,6 +223,7 @@ where } /// Get the instruction at the given instruction pointer. + #[inline] pub(crate) fn instruction_at( &self, ip: usize, @@ -218,6 +233,7 @@ where /// Iterate over all instructions in order. #[cfg(feature = "emit")] + #[inline] pub(crate) fn iter_instructions(&self) -> impl Iterator + '_ { self.logic.storage.iter() } @@ -251,18 +267,6 @@ pub(crate) enum UnitFn { /// The number of arguments the tuple takes. args: usize, }, - /// A unit variant of the type identified by the given hash. - UnitVariant { - /// The type hash of the empty variant. - hash: Hash, - }, - /// A tuple variant of the type identified by the given hash. - TupleVariant { - /// The type hash of the variant. - hash: Hash, - /// The number of arguments the tuple takes. - args: usize, - }, } impl TryClone for UnitFn { @@ -292,12 +296,6 @@ impl fmt::Display for UnitFn { Self::TupleStruct { hash, args } => { write!(f, "tuple hash={hash}, args={args}")?; } - Self::UnitVariant { hash } => { - write!(f, "empty-variant hash={hash}")?; - } - Self::TupleVariant { hash, args } => { - write!(f, "tuple-variant hash={hash}, args={args}")?; - } } Ok(()) diff --git a/crates/rune/src/runtime/value.rs b/crates/rune/src/runtime/value.rs index 7b459fee5..3c7519167 100644 --- a/crates/rune/src/runtime/value.rs +++ b/crates/rune/src/runtime/value.rs @@ -33,8 +33,7 @@ use super::{ AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, CallResultOnly, ConstValue, ConstValueKind, DynGuardedArgs, EnvProtocolCaller, Formatter, FromValue, Future, IntoOutput, Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol, ProtocolCaller, RawAnyObjGuard, Ref, - RuntimeError, Shared, Snapshot, Type, TypeInfo, Variant, Vec, VmErrorKind, VmIntegerRepr, - VmResult, + RuntimeError, Shared, Snapshot, Type, TypeInfo, Vec, VmErrorKind, VmIntegerRepr, VmResult, }; #[cfg(feature = "alloc")] use super::{Hasher, Tuple}; @@ -407,7 +406,6 @@ impl Value { Mutable::EmptyStruct(value) => Mutable::EmptyStruct(vm_try!(value.try_clone())), Mutable::TupleStruct(value) => Mutable::TupleStruct(vm_try!(value.try_clone())), Mutable::Struct(value) => Mutable::Struct(vm_try!(value.try_clone())), - Mutable::Variant(value) => Mutable::Variant(vm_try!(value.try_clone())), }, ReprRef::Any(..) => { break 'fallback; @@ -472,9 +470,6 @@ impl Value { Mutable::Struct(value) => { vm_try!(vm_write!(f, "{value:?}")); } - Mutable::Variant(value) => { - vm_try!(vm_write!(f, "{value:?}")); - } }; return VmResult::Ok(()); @@ -591,18 +586,6 @@ impl Value { VmResult::Ok(vm_try!(Value::try_from(TupleStruct { rtti, data }))) } - /// Construct an empty variant. - pub fn unit_variant(rtti: Arc) -> VmResult { - VmResult::Ok(vm_try!(Value::try_from(Variant::unit(rtti)))) - } - - /// Construct a tuple variant. - pub fn tuple_variant(rtti: Arc, vec: alloc::Vec) -> VmResult { - let data = vm_try!(OwnedTuple::try_from(vec)); - - VmResult::Ok(vm_try!(Value::try_from(Variant::tuple(rtti, data)))) - } - /// Drop the interior value. pub(crate) fn drop(self) -> VmResult<()> { match self.repr { @@ -674,7 +657,6 @@ impl Value { Mutable::EmptyStruct(empty) => Ok(TypeValue::EmptyStruct(empty)), Mutable::TupleStruct(tuple) => Ok(TypeValue::TupleStruct(tuple)), Mutable::Struct(object) => Ok(TypeValue::Struct(object)), - Mutable::Variant(object) => Ok(TypeValue::Variant(object)), }, ReprOwned::Any(value) => match value.type_hash() { OwnedTuple::HASH => Ok(TypeValue::Tuple(value.downcast()?)), @@ -1181,37 +1163,33 @@ impl Value { }); } (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { - let a = vm_try!(a.borrow_ref()); - let b = vm_try!(b.borrow_ref()); + let lhs = vm_try!(a.borrow_ref()); + let rhs = vm_try!(b.borrow_ref()); - match (&*a, &*b) { + match (&*lhs, &*rhs) { (Mutable::EmptyStruct(a), Mutable::EmptyStruct(b)) => { - if a.rtti.hash == b.rtti.hash { - // NB: don't get any future ideas, this must fall through to - // the VmError below since it's otherwise a comparison - // between two incompatible types. - // - // Other than that, all units are equal. + if a.rtti == b.rtti { return VmResult::Ok(true); } } (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::eq_with(&a.data, &b.data, Value::partial_eq_with, caller); } } (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::eq_with(&a.data, &b.data, Value::partial_eq_with, caller); } } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().hash == b.rtti().hash { - return Variant::partial_eq_with(a, b, caller); - } - } _ => {} } + + return err(VmErrorKind::UnsupportedBinaryOperation { + op: Protocol::PARTIAL_EQ.name, + lhs: lhs.type_info(), + rhs: rhs.type_info(), + }); } (ReprRef::Any(value), _) => match value.type_hash() { runtime::Vec::HASH => { @@ -1342,13 +1320,13 @@ impl Value { rhs: vm_try!(rhs.type_info()), }); } - (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { - let a = vm_try!(a.borrow_ref()); - let b = vm_try!(b.borrow_ref()); + (ReprRef::Mutable(lhs), ReprRef::Mutable(rhs)) => { + let lhs = vm_try!(lhs.borrow_ref()); + let rhs = vm_try!(rhs.borrow_ref()); - match (&*a, &*b) { + match (&*lhs, &*rhs) { (Mutable::EmptyStruct(a), Mutable::EmptyStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { // NB: don't get any future ideas, this must fall through to // the VmError below since it's otherwise a comparison // between two incompatible types. @@ -1358,22 +1336,23 @@ impl Value { } } (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::eq_with(&a.data, &b.data, Value::eq_with, caller); } } (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::eq_with(&a.data, &b.data, Value::eq_with, caller); } } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().hash == b.rtti().hash { - return Variant::eq_with(a, b, caller); - } - } _ => {} } + + return err(VmErrorKind::UnsupportedBinaryOperation { + op: Protocol::EQ.name, + lhs: lhs.type_info(), + rhs: rhs.type_info(), + }); } _ => {} } @@ -1427,13 +1406,13 @@ impl Value { rhs: vm_try!(rhs.type_info()), }) } - (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { - let a = vm_try!(a.borrow_ref()); - let b = vm_try!(b.borrow_ref()); + (ReprRef::Mutable(lhs), ReprRef::Mutable(rhs)) => { + let lhs = vm_try!(lhs.borrow_ref()); + let rhs = vm_try!(rhs.borrow_ref()); - match (&*a, &*b) { + match (&*lhs, &*rhs) { (Mutable::EmptyStruct(a), Mutable::EmptyStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { // NB: don't get any future ideas, this must fall through to // the VmError below since it's otherwise a comparison // between two incompatible types. @@ -1443,22 +1422,23 @@ impl Value { } } (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::partial_cmp_with(&a.data, &b.data, caller); } } (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::partial_cmp_with(&a.data, &b.data, caller); } } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().hash == b.rtti().hash { - return Variant::partial_cmp_with(a, b, caller); - } - } _ => {} } + + return err(VmErrorKind::UnsupportedBinaryOperation { + op: Protocol::PARTIAL_CMP.name, + lhs: lhs.type_info(), + rhs: rhs.type_info(), + }); } _ => {} } @@ -1503,13 +1483,13 @@ impl Value { ) -> VmResult { match (vm_try!(self.as_ref()), vm_try!(b.as_ref())) { (ReprRef::Inline(a), ReprRef::Inline(b)) => return a.cmp(b), - (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { - let a = vm_try!(a.borrow_ref()); - let b = vm_try!(b.borrow_ref()); + (ReprRef::Mutable(lhs), ReprRef::Mutable(rhs)) => { + let lhs = vm_try!(lhs.borrow_ref()); + let rhs = vm_try!(rhs.borrow_ref()); - match (&*a, &*b) { + match (&*lhs, &*rhs) { (Mutable::EmptyStruct(a), Mutable::EmptyStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { // NB: don't get any future ideas, this must fall through to // the VmError below since it's otherwise a comparison // between two incompatible types. @@ -1519,22 +1499,23 @@ impl Value { } } (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::cmp_with(&a.data, &b.data, caller); } } (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { + if a.rtti == b.rtti { return Vec::cmp_with(&a.data, &b.data, caller); } } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().hash == b.rtti().hash { - return Variant::cmp_with(a, b, caller); - } - } _ => {} } + + return VmResult::err(VmErrorKind::UnsupportedBinaryOperation { + op: Protocol::CMP.name, + lhs: lhs.type_info(), + rhs: rhs.type_info(), + }); } (ReprRef::Inline(lhs), rhs) => { return VmResult::err(VmErrorKind::UnsupportedBinaryOperation { @@ -1875,7 +1856,6 @@ from! { EmptyStruct => EmptyStruct, TupleStruct => TupleStruct, Struct => Struct, - Variant => Variant, } any_from! { @@ -1974,8 +1954,6 @@ pub enum TypeValue { TupleStruct(TupleStruct), /// An struct with a well-defined type. Struct(Struct), - /// The variant of an enum. - Variant(Variant), /// Not a typed immutable value. #[doc(hidden)] NotTypedInline(NotTypedInlineValue), @@ -1995,7 +1973,6 @@ impl TypeValue { TypeValue::EmptyStruct(empty) => empty.type_info(), TypeValue::TupleStruct(tuple) => tuple.type_info(), TypeValue::Struct(object) => object.type_info(), - TypeValue::Variant(empty) => empty.type_info(), TypeValue::NotTypedInline(value) => value.0.type_info(), TypeValue::NotTypedAnyObj(value) => value.0.type_info(), } @@ -2009,8 +1986,6 @@ pub(crate) enum Mutable { TupleStruct(TupleStruct), /// An struct with a well-defined type. Struct(Struct), - /// The variant of an enum. - Variant(Variant), } impl Mutable { @@ -2019,7 +1994,6 @@ impl Mutable { Mutable::EmptyStruct(empty) => empty.type_info(), Mutable::TupleStruct(tuple) => tuple.type_info(), Mutable::Struct(object) => object.type_info(), - Mutable::Variant(empty) => empty.type_info(), } } @@ -2029,10 +2003,9 @@ impl Mutable { /// *enum*, and not the type hash of the variant itself. pub(crate) fn type_hash(&self) -> Hash { match self { - Mutable::EmptyStruct(empty) => empty.rtti.hash, - Mutable::TupleStruct(tuple) => tuple.rtti.hash, - Mutable::Struct(object) => object.rtti.hash, - Mutable::Variant(variant) => variant.rtti().hash, + Mutable::EmptyStruct(empty) => empty.rtti.type_hash(), + Mutable::TupleStruct(tuple) => tuple.rtti.type_hash(), + Mutable::Struct(object) => object.rtti.type_hash(), } } } diff --git a/crates/rune/src/runtime/value/data.rs b/crates/rune/src/runtime/value/data.rs index 474e3d753..9f81276b5 100644 --- a/crates/rune/src/runtime/value/data.rs +++ b/crates/rune/src/runtime/value/data.rs @@ -27,7 +27,7 @@ impl EmptyStruct { /// Get type info for the typed tuple. pub fn type_info(&self) -> TypeInfo { - TypeInfo::typed(self.rtti.clone()) + TypeInfo::rtti(self.rtti.clone()) } } @@ -75,7 +75,7 @@ impl TupleStruct { /// Get type info for the typed tuple. pub fn type_info(&self) -> TypeInfo { - TypeInfo::typed(self.rtti.clone()) + TypeInfo::rtti(self.rtti.clone()) } /// Get the value at the given index in the tuple. @@ -153,7 +153,7 @@ impl Struct { /// Get type info for the typed object. pub(crate) fn type_info(&self) -> TypeInfo { - TypeInfo::typed(self.rtti.clone()) + TypeInfo::rtti(self.rtti.clone()) } } diff --git a/crates/rune/src/runtime/value/rtti.rs b/crates/rune/src/runtime/value/rtti.rs index 55f09bb67..b04639687 100644 --- a/crates/rune/src/runtime/value/rtti.rs +++ b/crates/rune/src/runtime/value/rtti.rs @@ -2,11 +2,13 @@ use core::borrow::Borrow; use core::cmp::Ordering; use core::hash; +use rust_alloc::sync::Arc; + use serde::{Deserialize, Serialize}; use crate::alloc::prelude::*; use crate::alloc::HashMap; -use crate::runtime::Value; +use crate::runtime::{TypeInfo, Value}; use crate::{Hash, ItemBuf}; /// Field accessor for a variant struct. @@ -33,32 +35,32 @@ impl<'a> Accessor<'a> { #[non_exhaustive] pub struct Rtti { /// The type hash of the type. - pub hash: Hash, + pub(crate) hash: Hash, /// If this type is a variant, designates the hash of the variant. - pub variant_hash: Hash, + pub(crate) variant_hash: Hash, /// The item of the type. - pub item: ItemBuf, + pub(crate) item: ItemBuf, /// Mapping from field names to their corresponding indexes. - pub fields: HashMap, usize>, + pub(crate) fields: HashMap, usize>, } impl Rtti { - /// Access a named field mutably from the given data. - pub fn get_field<'a, Q>(&self, data: &'a [Value], key: &Q) -> Option<&'a Value> - where - Box: Borrow, - Q: hash::Hash + Eq + ?Sized, - { - data.get(*self.fields.get(key)?) + /// Test if this RTTI matches the given raw hashes. + #[inline] + pub(crate) fn is(&self, hash: Hash, variant_hash: Hash) -> bool { + self.hash == hash && self.variant_hash == variant_hash } - /// Access a named field immutably from the given data. - pub fn get_field_mut<'a, Q>(&self, data: &'a mut [Value], key: &Q) -> Option<&'a mut Value> - where - Box: Borrow, - Q: hash::Hash + Eq + ?Sized, - { - data.get_mut(*self.fields.get(key)?) + /// Access the type hash of the RTTI. + #[inline] + pub fn type_hash(&self) -> Hash { + self.hash + } + + /// Access the type information for the RTTI. + #[inline] + pub fn type_info(self: Arc) -> TypeInfo { + TypeInfo::rtti(self) } } diff --git a/crates/rune/src/runtime/value/serde.rs b/crates/rune/src/runtime/value/serde.rs index 6a00f4968..ccc505609 100644 --- a/crates/rune/src/runtime/value/serde.rs +++ b/crates/rune/src/runtime/value/serde.rs @@ -44,8 +44,7 @@ impl ser::Serialize for Value { Mutable::TupleStruct(..) => { Err(ser::Error::custom("cannot serialize tuple structs")) } - Mutable::Struct(..) => Err(ser::Error::custom("cannot serialize objects structs")), - Mutable::Variant(..) => Err(ser::Error::custom("cannot serialize variants")), + Mutable::Struct(..) => Err(ser::Error::custom("cannot serialize structs")), }, ReprRef::Any(value) => match value.type_hash() { Option::::HASH => { diff --git a/crates/rune/src/runtime/variant.rs b/crates/rune/src/runtime/variant.rs deleted file mode 100644 index 87c5696e1..000000000 --- a/crates/rune/src/runtime/variant.rs +++ /dev/null @@ -1,217 +0,0 @@ -use core::cmp::Ordering; -use core::fmt; - -use ::rust_alloc::sync::Arc; - -use crate as rune; -use crate::alloc::clone::TryClone; -use crate::alloc::Box; - -use super::{ - Accessor, FromValue, Mutable, OwnedTuple, ProtocolCaller, ReprOwned, Rtti, RuntimeError, Tuple, - TypeInfo, Value, Vec, VmResult, -}; - -/// The variant of a type. -#[derive(TryClone)] -pub struct Variant { - pub(crate) rtti: Arc, - pub(crate) data: VariantData, -} - -impl Variant { - /// Construct a field accessor from this variant. - #[doc(hidden)] - pub fn accessor<'a>(&'a self, data: &'a [Value]) -> Accessor<'a> { - Accessor { - fields: &self.rtti.fields, - data, - } - } - - /// Try to access variant data as a tuple. - pub fn as_tuple(&self) -> Option<&Tuple> { - match &self.data { - VariantData::Tuple(tuple) => Some(tuple), - _ => None, - } - } - - /// Construct a unit variant. - pub(crate) fn unit(rtti: Arc) -> Self { - Self { - rtti, - data: VariantData::Empty, - } - } - - /// Construct a tuple variant. - pub(crate) fn tuple(rtti: Arc, tuple: OwnedTuple) -> Self { - Self { - rtti, - data: VariantData::Tuple(tuple), - } - } - - /// Construct a struct variant. - pub(crate) fn struct_(rtti: Arc, data: Box<[Value]>) -> Self { - Self { - rtti, - data: VariantData::Struct(data), - } - } - - /// Access the rtti of the variant. - pub fn rtti(&self) -> &Rtti { - &self.rtti - } - - /// Access the underlying variant data. - pub fn data(&self) -> &VariantData { - &self.data - } - - /// Access the underlying variant data mutably. - pub(crate) fn data_mut(&mut self) -> &mut VariantData { - &mut self.data - } - - /// Get type info for the variant. - pub(crate) fn type_info(&self) -> TypeInfo { - TypeInfo::typed(self.rtti.clone()) - } - - pub(crate) fn partial_eq_with( - a: &Self, - b: &Self, - caller: &mut dyn ProtocolCaller, - ) -> VmResult { - debug_assert_eq!( - a.rtti.hash, b.rtti.hash, - "comparison only makes sense if enum hashes match" - ); - - if a.rtti.hash != b.rtti.hash { - return VmResult::Ok(false); - } - - match (&a.data, &b.data) { - (VariantData::Empty, VariantData::Empty) => VmResult::Ok(true), - (VariantData::Tuple(a), VariantData::Tuple(b)) => { - Vec::eq_with(a, b, Value::partial_eq_with, caller) - } - (VariantData::Struct(a), VariantData::Struct(b)) => { - Vec::eq_with(a, b, Value::partial_eq_with, caller) - } - _ => VmResult::panic("data mismatch between variants"), - } - } - - pub(crate) fn eq_with(a: &Self, b: &Self, caller: &mut dyn ProtocolCaller) -> VmResult { - debug_assert_eq!( - a.rtti.hash, b.rtti.hash, - "comparison only makes sense if enum hashes match" - ); - - if a.rtti.hash != b.rtti.hash { - return VmResult::Ok(false); - } - - match (&a.data, &b.data) { - (VariantData::Empty, VariantData::Empty) => VmResult::Ok(true), - (VariantData::Tuple(a), VariantData::Tuple(b)) => { - Vec::eq_with(a, b, Value::eq_with, caller) - } - (VariantData::Struct(a), VariantData::Struct(b)) => { - Vec::eq_with(a, b, Value::eq_with, caller) - } - _ => VmResult::panic("data mismatch between variants"), - } - } - - pub(crate) fn partial_cmp_with( - a: &Self, - b: &Self, - caller: &mut dyn ProtocolCaller, - ) -> VmResult> { - debug_assert_eq!( - a.rtti.hash, b.rtti.hash, - "comparison only makes sense if enum hashes match" - ); - - match a.rtti.hash.partial_cmp(&b.rtti.hash) { - Some(Ordering::Equal) => {} - ordering => return VmResult::Ok(ordering), - } - - match (&a.data, &b.data) { - (VariantData::Empty, VariantData::Empty) => VmResult::Ok(Some(Ordering::Equal)), - (VariantData::Tuple(a), VariantData::Tuple(b)) => Vec::partial_cmp_with(a, b, caller), - (VariantData::Struct(a), VariantData::Struct(b)) => Vec::partial_cmp_with(a, b, caller), - _ => VmResult::panic("data mismatch between variants"), - } - } - - pub(crate) fn cmp_with( - a: &Self, - b: &Self, - caller: &mut dyn ProtocolCaller, - ) -> VmResult { - debug_assert_eq!( - a.rtti.hash, b.rtti.hash, - "comparison only makes sense if enum hashes match" - ); - - match a.rtti.hash.cmp(&b.rtti.hash) { - Ordering::Equal => {} - ordering => return VmResult::Ok(ordering), - } - - match (&a.data, &b.data) { - (VariantData::Empty, VariantData::Empty) => VmResult::Ok(Ordering::Equal), - (VariantData::Tuple(a), VariantData::Tuple(b)) => Vec::cmp_with(a, b, caller), - (VariantData::Struct(a), VariantData::Struct(b)) => Vec::cmp_with(a, b, caller), - _ => VmResult::panic("data mismatch between variants"), - } - } -} - -impl FromValue for Variant { - fn from_value(value: Value) -> Result { - match value.take_repr()? { - ReprOwned::Inline(value) => Err(RuntimeError::expected_variant(value.type_info())), - ReprOwned::Mutable(Mutable::Variant(value)) => Ok(value), - ReprOwned::Mutable(value) => Err(RuntimeError::expected_variant(value.type_info())), - ReprOwned::Any(value) => Err(RuntimeError::expected_variant(value.type_info())), - } - } -} - -/// The data of the variant. -#[derive(TryClone)] -pub enum VariantData { - /// A unit variant. - Empty, - /// A struct variant. - Struct(Box<[Value]>), - /// A tuple variant. - Tuple(OwnedTuple), -} - -impl fmt::Debug for Variant { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.rtti.item)?; - - match &self.data { - VariantData::Empty => {} - VariantData::Struct(st) => { - write!(f, "{:?}", st)?; - } - VariantData::Tuple(tuple) => { - write!(f, "{:?}", tuple)?; - } - } - - Ok(()) - } -} diff --git a/crates/rune/src/runtime/vm.rs b/crates/rune/src/runtime/vm.rs index dba24fee5..fb0841bcb 100644 --- a/crates/rune/src/runtime/vm.rs +++ b/crates/rune/src/runtime/vm.rs @@ -20,8 +20,8 @@ use super::{ GeneratorState, GuardedArgs, Inline, Inst, InstAddress, InstAssignOp, InstOp, InstRange, InstTarget, InstValue, InstVariant, Mutable, Object, Output, OwnedTuple, Pair, Panic, Protocol, ProtocolCaller, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, - ReprMut, ReprRef, RuntimeContext, Select, SelectFuture, Stack, Stream, Struct, Type, TypeCheck, - TypeHash, TypeInfo, TypeOf, Unit, UnitFn, UnitStorage, Value, Variant, VariantData, Vec, + ReprMut, ReprRef, RuntimeContext, Select, SelectFuture, Stack, Stream, Struct, TupleStruct, + Type, TypeCheck, TypeHash, TypeInfo, TypeOf, Unit, UnitFn, UnitStorage, Value, Vec, VmDiagnostics, VmDiagnosticsObj, VmError, VmErrorKind, VmExecution, VmHalt, VmIntegerRepr, VmResult, VmSendExecution, }; @@ -828,16 +828,11 @@ impl Vm { ReprRef::Mutable(target) => { let target = vm_try!(target.borrow_ref()); - let value = match &*target { - Mutable::Struct(target) => target.get(field), - Mutable::Variant(variant) => match variant.data() { - VariantData::Struct(target) => variant.rtti.get_field(target, field), - _ => return VmResult::Ok(None), - }, - _ => return VmResult::Ok(None), + let Mutable::Struct(data) = &*target else { + return VmResult::Ok(None); }; - let Some(value) = value else { + let Some(value) = data.get(field) else { return err(VmErrorKind::MissingField { target: target.type_info(), field: vm_try!(field.try_to_owned()), @@ -875,17 +870,10 @@ impl Vm { let target = vm_try!(target.borrow_ref()); match &*target { - Mutable::TupleStruct(tuple_struct) => match tuple_struct.data().get(index) { + Mutable::TupleStruct(data) => match data.get(index) { Some(value) => Ok(value.clone()), None => Err(target.type_info()), }, - Mutable::Variant(variant) => match variant.data() { - VariantData::Tuple(tuple) => match tuple.get(index) { - Some(value) => Ok(value.clone()), - None => Err(target.type_info()), - }, - _ => return VmResult::Ok(None), - }, _ => return VmResult::Ok(None), } } @@ -952,15 +940,8 @@ impl Vm { let mut unsupported = false; let result = BorrowMut::try_map(vm_try!(value.borrow_mut()), |kind| { - match kind { - Mutable::TupleStruct(tuple_struct) => return tuple_struct.get_mut(index), - Mutable::Variant(Variant { - data: VariantData::Tuple(tuple), - .. - }) => { - return tuple.get_mut(index); - } - _ => {} + if let Mutable::TupleStruct(data) = kind { + return data.get_mut(index); } unsupported = true; @@ -1084,18 +1065,8 @@ impl Vm { let mut unsupported = false; let result = BorrowMut::try_map(target, |value| { - match *value { - Mutable::Struct(ref mut target) => { - return target.get_mut(field); - } - Mutable::Variant(Variant { - ref rtti, - data: VariantData::Struct(ref mut st), - .. - }) => { - return rtti.get_field_mut(st, field); - } - _ => {} + if let Mutable::Struct(data) = value { + return data.get_mut(field); } unsupported = true; @@ -1140,24 +1111,14 @@ impl Vm { _ => VmResult::Ok(false), }, ReprRef::Mutable(target) => match &mut *vm_try!(target.borrow_mut()) { - Mutable::TupleStruct(tuple_struct) => { - if let Some(target) = tuple_struct.get_mut(index) { + Mutable::TupleStruct(data) => { + if let Some(target) = data.get_mut(index) { target.clone_from(from); return VmResult::Ok(true); } VmResult::Ok(false) } - Mutable::Variant(variant) => { - if let VariantData::Tuple(data) = variant.data_mut() { - if let Some(target) = data.get_mut(index) { - target.clone_from(from); - return VmResult::Ok(true); - } - } - - VmResult::Ok(false) - } _ => VmResult::Ok(false), }, ReprRef::Any(value) => match value.type_hash() { @@ -1224,18 +1185,8 @@ impl Vm { return VmResult::Ok(CallResult::Unsupported(target.clone())); } ReprRef::Mutable(target) => match *vm_try!(target.borrow_ref()) { - Mutable::Struct(ref typed_object) => { - if let Some(value) = typed_object.get(index.as_str()) { - vm_try!(out.store(&mut self.stack, || value.clone())); - return VmResult::Ok(CallResult::Ok(())); - } - } - Mutable::Variant(Variant { - ref rtti, - data: VariantData::Struct(ref data), - .. - }) => { - if let Some(value) = rtti.get_field(data, index.as_str()) { + Mutable::Struct(ref data) => { + if let Some(value) = data.get(index.as_str()) { vm_try!(out.store(&mut self.stack, || value.clone())); return VmResult::Ok(CallResult::Ok(())); } @@ -1281,14 +1232,6 @@ impl Vm { return VmResult::Ok(true); } } - Mutable::Variant(variant) => { - if let VariantData::Struct(data) = &mut variant.data { - if let Some(v) = variant.rtti.get_field_mut(data, field) { - v.clone_from(value); - return VmResult::Ok(true); - } - } - } _ => { return VmResult::Ok(false); } @@ -2714,22 +2657,6 @@ impl Vm { Function::from_tuple_struct(rtti.clone(), args) } - UnitFn::UnitVariant { hash } => { - let rtti = self - .unit - .lookup_rtti(hash) - .ok_or(VmErrorKind::MissingRtti { hash })?; - - Function::from_unit_variant(rtti.clone()) - } - UnitFn::TupleVariant { hash, args } => { - let rtti = self - .unit - .lookup_rtti(hash) - .ok_or(VmErrorKind::MissingRtti { hash })?; - - Function::from_tuple_variant(rtti.clone(), args) - } }, None => { let handler = self @@ -2999,10 +2926,9 @@ impl Vm { .lookup_rtti(hash) .ok_or(VmErrorKind::MissingRtti { hash })); - vm_try!(out.store( - &mut self.stack, - Mutable::EmptyStruct(EmptyStruct { rtti: rtti.clone() }) - )); + vm_try!(out.store(&mut self.stack, || VmResult::Ok(EmptyStruct { + rtti: rtti.clone() + }))); VmResult::Ok(()) } @@ -3022,13 +2948,10 @@ impl Vm { vm_try!(data.try_push(take(value))); } - vm_try!(out.store( - &mut self.stack, - Mutable::Struct(Struct { - rtti: rtti.clone(), - data: vm_try!(data.try_into()), - }) - )); + vm_try!(out.store(&mut self.stack, || VmResult::Ok(Struct { + rtti: rtti.clone(), + data: vm_try!(data.try_into()), + }))); VmResult::Ok(()) } @@ -3053,29 +2976,6 @@ impl Vm { VmResult::Ok(()) } - /// Operation to allocate an object variant. - #[cfg_attr(feature = "bench", inline(never))] - fn op_struct_variant(&mut self, addr: InstAddress, hash: Hash, out: Output) -> VmResult<()> { - let rtti = vm_try!(self - .unit - .lookup_rtti(hash) - .ok_or(VmErrorKind::MissingRtti { hash })); - - let mut data = vm_try!(alloc::Vec::try_with_capacity(rtti.fields.len())); - let values = vm_try!(self.stack.slice_at_mut(addr, rtti.fields.len())); - - for value in values { - vm_try!(data.try_push(take(value))); - } - - vm_try!(out.store( - &mut self.stack, - Mutable::Variant(Variant::struct_(rtti.clone(), vm_try!(data.try_into()))) - )); - - VmResult::Ok(()) - } - #[cfg_attr(feature = "bench", inline(never))] fn op_string(&mut self, slot: usize, out: Output) -> VmResult<()> { let string = vm_try!(self.unit.lookup_string(slot)); @@ -3311,12 +3211,17 @@ impl Vm { let is_match = 'out: { match vm_try!(value.as_ref()) { ReprRef::Mutable(value) => match &*vm_try!(value.borrow_ref()) { - Mutable::Variant(variant) => { - let rtti = variant.rtti(); - break 'out rtti.hash == enum_hash && rtti.hash == variant_hash; + Mutable::EmptyStruct(data) => { + let rtti = data.rtti(); + break 'out rtti.is(enum_hash, variant_hash); } - _ => { - break 'out false; + Mutable::TupleStruct(data) => { + let rtti = data.rtti(); + break 'out rtti.is(enum_hash, variant_hash); + } + Mutable::Struct(data) => { + let rtti = data.rtti(); + break 'out rtti.is(enum_hash, variant_hash); } }, ReprRef::Any(any) => match enum_hash { @@ -3564,41 +3469,15 @@ impl Vm { .ok_or(VmErrorKind::MissingRtti { hash })); let tuple = vm_try!(self.stack.slice_at_mut(addr, args)); - let tuple = vm_try!(tuple.iter_mut().map(take).try_collect()); + let data = vm_try!(tuple.iter_mut().map(take).try_collect()); vm_try!(out.store(&mut self.stack, || { - Value::tuple_struct(rtti.clone(), tuple) + TupleStruct { + rtti: rtti.clone(), + data, + } })); } - UnitFn::TupleVariant { - hash, - args: expected, - } => { - vm_try!(check_args(args, expected)); - - let rtti = vm_try!(self - .unit - .lookup_rtti(hash) - .ok_or(VmErrorKind::MissingRtti { hash })); - - let tuple = vm_try!(self.stack.slice_at_mut(addr, args)); - let tuple = vm_try!(tuple.iter_mut().map(take).try_collect()); - - vm_try!(out.store(&mut self.stack, || Value::tuple_variant( - rtti.clone(), - tuple - ))); - } - UnitFn::UnitVariant { hash } => { - vm_try!(check_args(args, 0)); - - let rtti = vm_try!(self - .unit - .lookup_rtti(hash) - .ok_or(VmErrorKind::MissingRtti { hash })); - - vm_try!(out.store(&mut self.stack, || Value::unit_variant(rtti.clone()))); - } } VmResult::Ok(()) @@ -3958,9 +3837,6 @@ impl Vm { } => { vm_try!(self.op_const_construct(addr, hash, count, out)); } - Inst::StructVariant { addr, hash, out } => { - vm_try!(self.op_struct_variant(addr, hash, out)); - } Inst::String { slot, out } => { vm_try!(self.op_string(slot, out)); } diff --git a/crates/rune/src/runtime/vm_error.rs b/crates/rune/src/runtime/vm_error.rs index da6283590..b6822d249 100644 --- a/crates/rune/src/runtime/vm_error.rs +++ b/crates/rune/src/runtime/vm_error.rs @@ -441,11 +441,6 @@ impl RuntimeError { }) } - /// Construct an expected error for a variant. - pub(crate) fn expected_variant(actual: TypeInfo) -> Self { - Self::new(VmErrorKind::ExpectedVariant { actual }) - } - /// Construct an expected expecting a unit struct. pub(crate) fn expected_unit_struct(actual: TypeInfo) -> Self { Self::new(VmErrorKind::ExpectedUnitStruct { actual }) diff --git a/crates/rune/src/tests.rs b/crates/rune/src/tests.rs index d165aa647..6f3683f0e 100644 --- a/crates/rune/src/tests.rs +++ b/crates/rune/src/tests.rs @@ -16,9 +16,9 @@ pub(crate) mod prelude { pub(crate) use crate::module::InstallWith; pub(crate) use crate::parse; pub(crate) use crate::runtime::{ - self, Bytes, Formatter, Function, InstAddress, MaybeTypeOf, Mutable, Object, Output, - OwnedTuple, Protocol, RawAnyGuard, Ref, ReprOwned, Stack, Tuple, TupleStruct, TypeHash, - TypeInfo, TypeOf, UnsafeToRef, Variant, VecTuple, VmErrorKind, VmResult, + self, Bytes, EmptyStruct, Formatter, Function, InstAddress, MaybeTypeOf, Object, Output, + OwnedTuple, Protocol, RawAnyGuard, Ref, Stack, Tuple, TupleStruct, TypeHash, TypeInfo, + TypeOf, UnsafeToRef, VecTuple, VmErrorKind, VmResult, }; pub(crate) use crate::support::Result; pub(crate) use crate::tests::{eval, run}; diff --git a/crates/rune/src/tests/function_guardedargs.rs b/crates/rune/src/tests/function_guardedargs.rs index 929bf28c2..06b5ed334 100644 --- a/crates/rune/src/tests/function_guardedargs.rs +++ b/crates/rune/src/tests/function_guardedargs.rs @@ -52,17 +52,14 @@ fn references_disallowed_for_tuple_variant() { let mut mine = MyAny; - let tuple = constructor.call::((&mine,)).unwrap(); - let tuple = tuple.as_tuple().unwrap(); - assert!(tuple.first().unwrap().borrow_ref::().is_err()); + let tuple = constructor.call::((&mine,)).unwrap(); + assert!(tuple.get(0).unwrap().borrow_ref::().is_err()); - let tuple = constructor.call::((&mut mine,)).unwrap(); - let tuple = tuple.as_tuple().unwrap(); - assert!(tuple.first().unwrap().borrow_ref::().is_err()); + let tuple = constructor.call::((&mut mine,)).unwrap(); + assert!(tuple.get(0).unwrap().borrow_ref::().is_err()); - let tuple = constructor.call::((mine,)).unwrap(); - let tuple = tuple.as_tuple().unwrap(); - assert!(tuple.first().unwrap().borrow_ref::().is_ok()); + let tuple = constructor.call::((mine,)).unwrap(); + assert!(tuple.get(0).unwrap().borrow_ref::().is_ok()); } #[test] diff --git a/crates/rune/src/tests/vm_function.rs b/crates/rune/src/tests/vm_function.rs index 3bf06d34f..54d1ed7d6 100644 --- a/crates/rune/src/tests/vm_function.rs +++ b/crates/rune/src/tests/vm_function.rs @@ -34,10 +34,7 @@ fn test_function() { assert!(function.call::(()).into_result().is_err()); let value: Value = function.call((1i64,)).unwrap(); - assert!(matches!( - value.take_repr().unwrap(), - ReprOwned::Mutable(Mutable::Variant(..)) - )); + assert!(rune::from_value::(value).is_ok()); // ptr to dynamic function. let function: Function = rune! { @@ -47,10 +44,7 @@ fn test_function() { assert!(function.call::(()).into_result().is_err()); let value: Value = function.call((1i64,)).unwrap(); - assert!(matches!( - value.take_repr().unwrap(), - ReprOwned::Mutable(Mutable::TupleStruct(..)) - )); + assert!(crate::from_value::(value).is_ok()); // non-capturing closure == free function let function: Function = rune! {