diff --git a/crates/rune/src/compile/ir/interpreter.rs b/crates/rune/src/compile/ir/interpreter.rs index 38acb8390..3659e859b 100644 --- a/crates/rune/src/compile/ir/interpreter.rs +++ b/crates/rune/src/compile/ir/interpreter.rs @@ -7,7 +7,10 @@ use crate::compile::meta; use crate::compile::{self, IrErrorKind, ItemId, ModId, WithSpan}; use crate::hir; use crate::query::{Query, Used}; -use crate::runtime::{BorrowRefRepr, ConstValue, Mutable, Object, OwnedTuple, RefRepr, Value}; +use crate::runtime::{ + self, BorrowRefRepr, ConstValue, Mutable, Object, OwnedTuple, RefRepr, Value, +}; +use crate::TypeHash; /// The interpreter that executed [Ir][crate::ir::Ir]. pub struct Interpreter<'a, 'arena> { @@ -224,11 +227,6 @@ impl ir::Scopes { match target { BorrowRefRepr::Mutable(value) => { match &*value { - Mutable::Vec(vec) => { - if let Some(value) = vec.get(*index) { - return Ok(value.clone()); - } - } Mutable::Tuple(tuple) => { if let Some(value) = tuple.get(*index) { return Ok(value.clone()); @@ -242,11 +240,26 @@ impl ir::Scopes { } }; } - actual => { + BorrowRefRepr::Any(value) => match value.type_hash() { + runtime::Vec::HASH => { + let vec = value.borrow_ref::().with_span(ir_target)?; + + if let Some(value) = vec.get(*index) { + return Ok(value.clone()); + } + } + _ => { + return Err(compile::Error::expected_type::( + ir_target, + value.type_info(), + )); + } + }, + value => { return Err(compile::Error::expected_type::( ir_target, - actual.type_info(), - )) + value.type_info(), + )); } } @@ -300,35 +313,47 @@ impl ir::Scopes { ir::IrTargetKind::Index(target, index) => { let target = self.get_target(target)?; - let mut target = match target.as_ref_repr().with_span(ir_target)? { - RefRepr::Mutable(current) => current.borrow_mut().with_span(ir_target)?, - actual => { + match target.as_ref_repr().with_span(ir_target)? { + RefRepr::Inline(value) => { return Err(compile::Error::expected_type::( ir_target, - actual.type_info().with_span(ir_target)?, + value.type_info(), )); } - }; + RefRepr::Mutable(current) => { + let mut mutable = current.borrow_mut().with_span(ir_target)?; - match &mut *target { - Mutable::Vec(vec) => { - if let Some(current) = vec.get_mut(*index) { - *current = value; - return Ok(()); - } + match &mut *mutable { + Mutable::Tuple(tuple) => { + if let Some(current) = tuple.get_mut(*index) { + *current = value; + return Ok(()); + } + } + value => { + return Err(compile::Error::expected_type::( + ir_target, + value.type_info(), + )); + } + }; } - Mutable::Tuple(tuple) => { - if let Some(current) = tuple.get_mut(*index) { - *current = value; - return Ok(()); + RefRepr::Any(any) => match any.type_hash() { + runtime::Vec::HASH => { + let mut vec = any.borrow_mut::().with_span(ir_target)?; + + if let Some(current) = vec.get_mut(*index) { + *current = value; + return Ok(()); + } } - } - actual => { - return Err(compile::Error::expected_type::( - ir_target, - actual.type_info(), - )); - } + _ => { + return Err(compile::Error::expected_type::( + ir_target, + any.type_info(), + )); + } + }, }; Err(compile::Error::msg(ir_target, "missing index")) @@ -382,40 +407,49 @@ impl ir::Scopes { ir::IrTargetKind::Index(target, index) => { let current = self.get_target(target)?; - let mut value = match current.as_ref_repr().with_span(ir_target)? { - RefRepr::Mutable(value) => value.borrow_mut().with_span(ir_target)?, - actual => { - return Err(compile::Error::expected_type::( - ir_target, - actual.type_info().with_span(ir_target)?, - )); - } - }; + match current.as_ref_repr().with_span(ir_target)? { + RefRepr::Mutable(value) => { + let mut value = value.borrow_mut().with_span(ir_target)?; - match &mut *value { - Mutable::Vec(vec) => { - let value = vec.get_mut(*index).ok_or_else(|| { - compile::Error::new( + match &mut *value { + Mutable::Tuple(tuple) => { + let value = tuple.get_mut(*index).ok_or_else(|| { + compile::Error::new( + ir_target, + IrErrorKind::MissingIndex { index: *index }, + ) + })?; + + op(value) + } + actual => Err(compile::Error::expected_type::( ir_target, - IrErrorKind::MissingIndex { index: *index }, - ) - })?; - - op(value) + actual.type_info(), + )), + } } - Mutable::Tuple(tuple) => { - let value = tuple.get_mut(*index).ok_or_else(|| { - compile::Error::new( - ir_target, - IrErrorKind::MissingIndex { index: *index }, - ) - })?; + RefRepr::Any(value) => match value.type_hash() { + runtime::Vec::HASH => { + let mut vec = + value.borrow_mut::().with_span(ir_target)?; - op(value) - } + let value = vec.get_mut(*index).ok_or_else(|| { + compile::Error::new( + ir_target, + IrErrorKind::MissingIndex { index: *index }, + ) + })?; + + op(value) + } + _ => Err(compile::Error::expected_type::( + ir_target, + value.type_info(), + )), + }, actual => Err(compile::Error::expected_type::( ir_target, - actual.type_info(), + actual.type_info().with_span(ir_target)?, )), } } diff --git a/crates/rune/src/modules/future.rs b/crates/rune/src/modules/future.rs index 4fb1dbca4..fa238c85a 100644 --- a/crates/rune/src/modules/future.rs +++ b/crates/rune/src/modules/future.rs @@ -3,10 +3,10 @@ use crate as rune; use crate::alloc::Vec; use crate::runtime::{ - BorrowRefRepr, Future, Inline, Mut, Mutable, RefRepr, SelectFuture, Value, VmErrorKind, + self, BorrowRefRepr, Future, Inline, Mut, Mutable, RefRepr, SelectFuture, Value, VmErrorKind, VmResult, }; -use crate::{ContextError, Module}; +use crate::{ContextError, Module, TypeHash}; /// Asynchronous computations. #[rune::module(::std::future)] @@ -106,7 +106,7 @@ async fn join(value: Value) -> VmResult { Inline::Unit => VmResult::Ok(Value::unit()), value => VmResult::err([ VmErrorKind::bad_argument(0), - VmErrorKind::expected::(value.type_info()), + VmErrorKind::expected::(value.type_info()), ]), }, BorrowRefRepr::Mutable(value) => match *value { @@ -118,21 +118,24 @@ async fn join(value: Value) -> VmResult { VmResult::Ok(vm_try!(result)) } - Mutable::Vec(ref vec) => { + ref value => VmResult::err([ + VmErrorKind::bad_argument(0), + VmErrorKind::expected::(value.type_info()), + ]), + }, + BorrowRefRepr::Any(value) => match value.type_hash() { + runtime::Vec::HASH => { + let vec = vm_try!(value.borrow_ref::()); let result = try_join_impl(vec.iter(), vec.len(), |vec| { VmResult::Ok(vm_try!(Value::vec(vec))) }) .await; VmResult::Ok(vm_try!(result)) } - ref value => VmResult::err([ + _ => VmResult::err([ VmErrorKind::bad_argument(0), - VmErrorKind::expected::(value.type_info()), + VmErrorKind::expected::(value.type_info()), ]), }, - BorrowRefRepr::Any(value) => VmResult::err([ - VmErrorKind::bad_argument(0), - VmErrorKind::expected::(value.type_info()), - ]), } } diff --git a/crates/rune/src/modules/vec.rs b/crates/rune/src/modules/vec.rs index bdb649e4b..2f933e94a 100644 --- a/crates/rune/src/modules/vec.rs +++ b/crates/rune/src/modules/vec.rs @@ -80,7 +80,7 @@ pub fn module() -> Result { m.function_meta(index_get)?; m.function_meta(index_set)?; m.function_meta(resize)?; - m.function_meta(string_debug)?; + m.function_meta(string_debug__meta)?; m.function_meta(clone__meta)?; m.implement_trait::(rune::item!(::std::clone::Clone))?; @@ -612,7 +612,7 @@ fn resize(this: &mut Vec, new_len: usize, value: Value) -> VmResult<()> { /// let vec = [1, 2, 3]; /// assert_eq!(format!("{:?}", vec), "[1, 2, 3]"); /// ``` -#[rune::function(instance, protocol = STRING_DEBUG)] +#[rune::function(keep, instance, protocol = STRING_DEBUG)] fn string_debug(this: &Vec, f: &mut Formatter) -> VmResult<()> { Vec::string_debug_with(this, f, &mut EnvProtocolCaller) } diff --git a/crates/rune/src/runtime/const_value.rs b/crates/rune/src/runtime/const_value.rs index 92775afb5..912eb0801 100644 --- a/crates/rune/src/runtime/const_value.rs +++ b/crates/rune/src/runtime/const_value.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use crate as rune; use crate::alloc::prelude::*; use crate::alloc::{self, HashMap}; +use crate::runtime; use crate::{Hash, TypeHash}; use super::{ @@ -130,18 +131,12 @@ impl ConstValueKind { fn type_info(&self) -> TypeInfo { match self { ConstValueKind::Inline(value) => value.type_info(), - ConstValueKind::String(..) => { - TypeInfo::static_type(crate::runtime::static_type::STRING) - } - ConstValueKind::Bytes(..) => TypeInfo::static_type(crate::runtime::static_type::BYTES), - ConstValueKind::Vec(..) => TypeInfo::static_type(crate::runtime::static_type::VEC), - ConstValueKind::Tuple(..) => TypeInfo::static_type(crate::runtime::static_type::TUPLE), - ConstValueKind::Object(..) => { - TypeInfo::static_type(crate::runtime::static_type::OBJECT) - } - ConstValueKind::Option(..) => { - TypeInfo::static_type(crate::runtime::static_type::OPTION) - } + ConstValueKind::String(..) => TypeInfo::static_type(runtime::static_type::STRING), + ConstValueKind::Bytes(..) => TypeInfo::static_type(runtime::static_type::BYTES), + ConstValueKind::Vec(..) => TypeInfo::static_type(runtime::static_type::VEC), + ConstValueKind::Tuple(..) => TypeInfo::static_type(runtime::static_type::TUPLE), + ConstValueKind::Object(..) => TypeInfo::static_type(runtime::static_type::OBJECT), + ConstValueKind::Option(..) => TypeInfo::static_type(runtime::static_type::OPTION), ConstValueKind::Struct(hash, ..) => TypeInfo::any_type_info(AnyTypeInfo::new( RawStr::from_str("constant struct"), *hash, @@ -243,15 +238,6 @@ impl ConstValue { Some(some) => Some(Box::try_new(Self::from_value_ref(some)?)?), None => None, }), - Mutable::Vec(ref vec) => { - let mut const_vec = Vec::try_with_capacity(vec.len())?; - - for value in vec { - const_vec.try_push(Self::from_value_ref(value)?)?; - } - - ConstValueKind::Vec(const_vec) - } Mutable::Tuple(ref tuple) => { let mut const_tuple = Vec::try_with_capacity(tuple.len())?; @@ -287,6 +273,16 @@ impl ConstValue { let s = value.borrow_ref::()?; ConstValueKind::Bytes(s.try_to_owned()?) } + runtime::Vec::HASH => { + let vec = value.borrow_ref::()?; + let mut const_vec = Vec::try_with_capacity(vec.len())?; + + for value in vec.iter() { + const_vec.try_push(Self::from_value_ref(value)?)?; + } + + ConstValueKind::Vec(const_vec) + } _ => { return Err(RuntimeError::from(VmErrorKind::ConstNotSupported { actual: value.type_info(), diff --git a/crates/rune/src/runtime/value.rs b/crates/rune/src/runtime/value.rs index 75532aa85..406250fa8 100644 --- a/crates/rune/src/runtime/value.rs +++ b/crates/rune/src/runtime/value.rs @@ -26,7 +26,8 @@ use crate::alloc::fmt::TryWrite; use crate::alloc::prelude::*; use crate::alloc::{self, String}; use crate::compile::meta; -use crate::{Any, Hash}; +use crate::runtime; +use crate::{Any, Hash, TypeHash}; use super::static_type; use super::{ @@ -416,14 +417,13 @@ impl Value { pub(crate) fn clone_with(&self, caller: &mut dyn ProtocolCaller) -> VmResult { 'fallback: { - let value = match vm_try!(self.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => { + let value = match vm_try!(self.as_ref_repr()) { + RefRepr::Inline(value) => { return VmResult::Ok(Self { repr: Repr::Inline(*value), }); } - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Vec(value) => Mutable::Vec(vm_try!(value.try_clone())), + RefRepr::Mutable(value) => match &*vm_try!(value.borrow_ref()) { Mutable::Tuple(value) => Mutable::Tuple(vm_try!(value.try_clone())), Mutable::Object(value) => Mutable::Object(vm_try!(value.try_clone())), Mutable::Stream(value) => Mutable::Stream(vm_try!(value.try_clone())), @@ -439,7 +439,7 @@ impl Value { break 'fallback; } }, - BorrowRefRepr::Any(..) => { + RefRepr::Any(..) => { break 'fallback; } }; @@ -491,9 +491,6 @@ impl Value { }; match &*vm_try!(value.borrow_ref()) { - Mutable::Vec(value) => { - vm_try!(Vec::string_debug_with(value, f, caller)); - } Mutable::Tuple(value) => { vm_try!(vm_write!(f, "{value:?}")); } @@ -811,16 +808,6 @@ impl Value { as_result, } - into! { - /// Coerce into [`Vec`]. - Vec(Vec), - into_vec_ref, - into_vec_mut, - borrow_vec_ref, - borrow_vec_mut, - into_vec, - } - into! { /// Coerce into a [`Function`]. Function(Function), @@ -1109,82 +1096,98 @@ impl Value { caller: &mut dyn ProtocolCaller, ) -> VmResult { 'fallback: { - let a = vm_try!(self.borrow_ref_repr()); - - let a = match (&a, vm_try!(b.borrow_ref_repr())) { - (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { - return VmResult::Ok(vm_try!(a.partial_eq(b))); - } - (BorrowRefRepr::Inline(lhs), rhs) => { - return err(VmErrorKind::UnsupportedBinaryOperation { - op: Protocol::PARTIAL_EQ.name, - lhs: lhs.type_info(), - rhs: rhs.type_info(), - }); - } - (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b2)) => match (&**a, &*b2) { - (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. - return VmResult::Ok(true); - } - - break 'fallback; + let a = 'mutable: { + match (vm_try!(self.as_ref_repr()), vm_try!(b.borrow_ref_repr())) { + (RefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { + return VmResult::Ok(vm_try!(a.partial_eq(b))); } - (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::eq_with(&a.data, &b.data, Value::partial_eq_with, caller); - } - - break 'fallback; + (RefRepr::Inline(a), b) => { + return err(VmErrorKind::UnsupportedBinaryOperation { + op: Protocol::PARTIAL_EQ.name, + lhs: a.type_info(), + rhs: b.type_info(), + }); } - (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Object::eq_with( - &a.data, - &b.data, - Value::partial_eq_with, - caller, - ); + (RefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => { + let a = vm_try!(a.borrow_ref()); + + match (&*a, &*b) { + (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. + return VmResult::Ok(true); + } + + break 'fallback; + } + (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Vec::eq_with( + &a.data, + &b.data, + Value::partial_eq_with, + caller, + ); + } + + break 'fallback; + } + (Mutable::Struct(a), Mutable::Struct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Object::eq_with( + &a.data, + &b.data, + Value::partial_eq_with, + caller, + ); + } + + break 'fallback; + } + (Mutable::Variant(a), Mutable::Variant(b)) => { + if a.rtti().enum_hash == b.rtti().enum_hash { + return Variant::partial_eq_with(a, b, caller); + } + + break 'fallback; + } + (Mutable::Option(a), Mutable::Option(b)) => match (a, b) { + (Some(a), Some(b)) => return Value::partial_eq_with(a, b, caller), + (None, None) => return VmResult::Ok(true), + _ => return VmResult::Ok(false), + }, + (Mutable::Result(a), Mutable::Result(b)) => match (a, b) { + (Ok(a), Ok(b)) => return Value::partial_eq_with(a, b, caller), + (Err(a), Err(b)) => return Value::partial_eq_with(a, b, caller), + _ => return VmResult::Ok(false), + }, + _ => {} } - break 'fallback; + break 'mutable a; } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().enum_hash == b.rtti().enum_hash { - return Variant::partial_eq_with(a, b, caller); + (RefRepr::Any(value), _) => match value.type_hash() { + runtime::Vec::HASH => { + let vec = vm_try!(value.borrow_ref::()); + return Vec::partial_eq_with(&vec, b.clone(), caller); } - + _ => { + break 'fallback; + } + }, + _ => { break 'fallback; } - (Mutable::Option(a), Mutable::Option(b)) => match (a, b) { - (Some(a), Some(b)) => return Value::partial_eq_with(a, b, caller), - (None, None) => return VmResult::Ok(true), - _ => return VmResult::Ok(false), - }, - (Mutable::Result(a), Mutable::Result(b)) => match (a, b) { - (Ok(a), Ok(b)) => return Value::partial_eq_with(a, b, caller), - (Err(a), Err(b)) => return Value::partial_eq_with(a, b, caller), - _ => return VmResult::Ok(false), - }, - (a, _) => a, - }, - _ => break 'fallback, + } }; // Special cases. - match a { - Mutable::Vec(a) => { - return Vec::partial_eq_with(a, b.clone(), caller); - } - Mutable::Tuple(a) => { - return Vec::partial_eq_with(a, b.clone(), caller); - } - _ => {} + if let Mutable::Tuple(a) = &*a { + return Vec::partial_eq_with(a, b.clone(), caller); } } @@ -1245,15 +1248,15 @@ impl Value { }); } }, - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Tuple(tuple) => { + BorrowRefRepr::Mutable(value) => { + if let Mutable::Tuple(tuple) = &*value { return Tuple::hash_with(tuple, hasher, caller); } - Mutable::Vec(vec) => { - return Vec::hash_with(vec, hasher, caller); - } - _ => {} - }, + } + BorrowRefRepr::Any(value) if value.type_hash() == runtime::Vec::HASH => { + let vec = vm_try!(value.borrow_ref::()); + return Vec::hash_with(&vec, hasher, caller); + } _ => {} } @@ -1305,9 +1308,6 @@ impl Value { }); } (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => match (&*a, &*b) { - (Mutable::Vec(a), Mutable::Vec(b)) => { - return Vec::eq_with(a, b, Value::eq_with, caller); - } (Mutable::Tuple(a), Mutable::Tuple(b)) => { return Vec::eq_with(a, b, Value::eq_with, caller); } @@ -1407,9 +1407,6 @@ impl Value { }) } (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => match (&*a, &*b) { - (Mutable::Vec(a), Mutable::Vec(b)) => { - return Vec::partial_cmp_with(a, b, caller); - } (Mutable::Tuple(a), Mutable::Tuple(b)) => { return Vec::partial_cmp_with(a, b, caller); } @@ -1502,9 +1499,6 @@ impl Value { ) { (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => return a.cmp(b), (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => match (&*a, &*b) { - (Mutable::Vec(a), Mutable::Vec(b)) => { - return Vec::cmp_with(a, b, caller); - } (Mutable::Tuple(a), Mutable::Tuple(b)) => { return Vec::cmp_with(a, b, caller); } @@ -1612,7 +1606,7 @@ impl Value { /// Test if the value is inline. pub(crate) fn is_inline(&self) -> bool { - matches!(self.repr, Repr::Any(..) | Repr::Inline(..)) + matches!(self.repr, Repr::Inline(..)) } /// Coerce into a checked [`Inline`] object. @@ -1887,7 +1881,6 @@ inline_from! { from! { Function => Function, - Vec => Vec, EmptyStruct => EmptyStruct, TupleStruct => TupleStruct, Struct => Struct, @@ -1905,6 +1898,7 @@ any_from! { super::Format, super::ControlFlow, super::GeneratorState, + super::Vec, } from_container! { @@ -2024,8 +2018,6 @@ impl TypeValue { } pub(crate) enum Mutable { - /// A vector containing any values. - Vec(Vec), /// A tuple. Tuple(OwnedTuple), /// An object. @@ -2055,7 +2047,6 @@ pub(crate) enum Mutable { impl Mutable { pub(crate) fn type_info(&self) -> TypeInfo { match self { - Mutable::Vec(..) => TypeInfo::static_type(static_type::VEC), Mutable::Tuple(..) => TypeInfo::static_type(static_type::TUPLE), Mutable::Object(..) => TypeInfo::static_type(static_type::OBJECT), Mutable::Future(..) => TypeInfo::static_type(static_type::FUTURE), @@ -2077,7 +2068,6 @@ impl Mutable { /// *enum*, and not the type hash of the variant itself. pub(crate) fn type_hash(&self) -> Hash { match self { - Mutable::Vec(..) => static_type::VEC.hash, Mutable::Tuple(..) => static_type::TUPLE.hash, Mutable::Object(..) => static_type::OBJECT.hash, Mutable::Future(..) => static_type::FUTURE.hash, diff --git a/crates/rune/src/runtime/value/serde.rs b/crates/rune/src/runtime/value/serde.rs index c0f84218f..37bb220a8 100644 --- a/crates/rune/src/runtime/value/serde.rs +++ b/crates/rune/src/runtime/value/serde.rs @@ -2,7 +2,7 @@ use core::fmt; use crate::alloc; use crate::alloc::prelude::*; -use crate::runtime::{BorrowRefRepr, Bytes, Inline, Mutable, Object, Vec}; +use crate::runtime::{self, BorrowRefRepr, Bytes, Inline, Mutable, Object, Vec}; use crate::TypeHash; use serde::de::{self, Deserialize as _, Error as _}; @@ -38,15 +38,6 @@ impl ser::Serialize for Value { Inline::Ordering(..) => Err(ser::Error::custom("cannot serialize orderings")), }, BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Vec(vec) => { - let mut serializer = serializer.serialize_seq(Some(vec.len()))?; - - for value in vec { - serializer.serialize_element(value)?; - } - - serializer.end() - } Mutable::Tuple(tuple) => { let mut serializer = serializer.serialize_seq(Some(tuple.len()))?; @@ -91,6 +82,16 @@ impl ser::Serialize for Value { let bytes = value.borrow_ref::().map_err(S::Error::custom)?; serializer.serialize_bytes(bytes.as_slice()) } + runtime::Vec::HASH => { + let vec = value.borrow_ref::().map_err(S::Error::custom)?; + let mut serializer = serializer.serialize_seq(Some(vec.len()))?; + + for value in vec.iter() { + serializer.serialize_element(value)?; + } + + serializer.end() + } _ => Err(ser::Error::custom("cannot serialize external references")), }, } diff --git a/crates/rune/src/runtime/vec.rs b/crates/rune/src/runtime/vec.rs index 98ba6a090..9afa660d2 100644 --- a/crates/rune/src/runtime/vec.rs +++ b/crates/rune/src/runtime/vec.rs @@ -40,8 +40,7 @@ use super::{ /// ``` #[derive(Default, Any)] #[repr(transparent)] -#[rune(builtin, static_type = VEC)] -#[rune(from_value = Value::into_vec, from_value_ref = Value::into_vec_ref, from_value_mut = Value::into_vec_mut)] +#[rune(static_type = VEC)] pub struct Vec { inner: alloc::Vec, } @@ -536,7 +535,7 @@ where T: FromValue, { fn from_value(value: Value) -> Result { - let vec = value.into_vec()?; + let vec = value.into_any::()?; let mut output = ::rust_alloc::vec::Vec::with_capacity(vec.len()); @@ -553,7 +552,7 @@ where T: FromValue, { fn from_value(value: Value) -> Result { - let vec = value.into_vec()?; + let vec = value.into_any::()?; let mut output = alloc::Vec::try_with_capacity(vec.len())?; @@ -569,10 +568,8 @@ impl UnsafeToRef for [Value] { type Guard = RawAnyGuard; unsafe fn unsafe_to_ref<'a>(value: Value) -> VmResult<(&'a Self, Self::Guard)> { - let vec = vm_try!(value.into_vec_ref()); + let vec = vm_try!(value.into_any_ref::()); let (vec, guard) = Ref::into_raw(vec); - // SAFETY: we're holding onto the guard for the vector here, so it is - // live. VmResult::Ok((vec.as_ref().as_slice(), guard)) } } diff --git a/crates/rune/src/runtime/vec_tuple.rs b/crates/rune/src/runtime/vec_tuple.rs index 697353c04..81595cd94 100644 --- a/crates/rune/src/runtime/vec_tuple.rs +++ b/crates/rune/src/runtime/vec_tuple.rs @@ -27,7 +27,7 @@ macro_rules! impl_from_value_tuple_vec { $($ty: FromValue,)* { fn from_value(value: Value) -> Result { - let vec = value.into_vec_ref()?; + let vec = value.into_any_ref::<$crate::runtime::Vec>()?; let [$($var,)*] = vec.as_slice() else { return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength { diff --git a/crates/rune/src/runtime/vm.rs b/crates/rune/src/runtime/vm.rs index 80cc2b887..f315fbebe 100644 --- a/crates/rune/src/runtime/vm.rs +++ b/crates/rune/src/runtime/vm.rs @@ -11,6 +11,7 @@ use crate::alloc::prelude::*; use crate::alloc::{self, String}; use crate::hash::{Hash, IntoHash, ToTypeHash}; use crate::modules::{option, result}; +use crate::runtime; use crate::Any; use super::{ @@ -482,8 +483,8 @@ impl Vm { /// this call will panic as we are trying to free the metadata relatedc to /// the reference. /// - /// [`Mut`]: crate::runtime::Mut - /// [`Ref`]: crate::runtime::Ref + /// [`Mut`]: runtime::Mut + /// [`Ref`]: runtime::Ref pub fn call( &mut self, name: impl ToTypeHash, @@ -522,8 +523,8 @@ impl Vm { /// this call will panic as we are trying to free the metadata relatedc to /// the reference. /// - /// [`Mut`]: crate::runtime::Mut - /// [`Ref`]: crate::runtime::Ref + /// [`Mut`]: runtime::Mut + /// [`Ref`]: runtime::Ref pub fn call_with_diagnostics( &mut self, name: impl ToTypeHash, @@ -566,8 +567,8 @@ impl Vm { /// this call will panic as we are trying to free the metadata relatedc to /// the reference. /// - /// [`Mut`]: crate::runtime::Mut - /// [`Ref`]: crate::runtime::Ref + /// [`Mut`]: runtime::Mut + /// [`Ref`]: runtime::Ref pub async fn async_call(&mut self, name: N, args: A) -> Result where N: ToTypeHash, @@ -682,7 +683,7 @@ impl Vm { } fn called_function_hook(&self, hash: Hash) -> VmResult<()> { - crate::runtime::env::exclusive(|_, _, diagnostics| { + runtime::env::exclusive(|_, _, diagnostics| { if let Some(diagnostics) = diagnostics { vm_try!(diagnostics.function_used(hash, self.ip())); } @@ -868,10 +869,6 @@ impl Vm { Some(value) => Ok(value.clone()), None => Err(target.type_info()), }, - Mutable::Vec(vec) => match vec.get(index) { - Some(value) => Ok(value.clone()), - None => Err(target.type_info()), - }, Mutable::Result(result) => match (index, result) { (0, Ok(value)) => Ok(value.clone()), (0, Err(value)) => Ok(value.clone()), @@ -900,6 +897,14 @@ impl Vm { (0, GeneratorState::Complete(value)) => Ok(value.clone()), _ => Err(target.type_info()), }, + runtime::Vec::HASH => { + let vec = vm_try!(target.borrow_ref::()); + + match vec.get(index) { + Some(value) => Ok(value.clone()), + None => Err(target.type_info()), + } + } _ => { return VmResult::Ok(None); } @@ -927,7 +932,6 @@ impl Vm { let result = BorrowMut::try_map(vm_try!(value.borrow_mut()), |kind| { match kind { Mutable::Tuple(tuple) => return tuple.get_mut(index), - Mutable::Vec(vec) => return vec.get_mut(index), Mutable::Result(result) => match (index, result) { (0, Ok(value)) => return Some(value), (0, Err(value)) => return Some(value), @@ -983,6 +987,19 @@ impl Vm { index: VmIntegerRepr::from(index), }) } + runtime::Vec::HASH => { + let vec = vm_try!(value.borrow_mut::()); + let result = BorrowMut::try_map(vec, |vec| vec.get_mut(index)); + + if let Ok(value) = result { + return VmResult::Ok(Some(value)); + } + + err(VmErrorKind::MissingIndexInteger { + target: TypeInfo::from(GeneratorState::INFO), + index: VmIntegerRepr::from(index), + }) + } _ => VmResult::Ok(None), }, _ => VmResult::Ok(None), @@ -1042,7 +1059,7 @@ impl Vm { } /// Implementation of getting a string index on an object-like type. - fn try_tuple_like_index_set(target: &Value, index: usize, value: &Value) -> VmResult { + fn try_tuple_like_index_set(target: &Value, index: usize, from: &Value) -> VmResult { match vm_try!(target.as_ref_repr()) { RefRepr::Inline(target) => match target { Inline::Unit => VmResult::Ok(false), @@ -1051,15 +1068,7 @@ impl Vm { RefRepr::Mutable(target) => match &mut *vm_try!(target.borrow_mut()) { Mutable::Tuple(tuple) => { if let Some(target) = tuple.get_mut(index) { - target.clone_from(value); - return VmResult::Ok(true); - } - - VmResult::Ok(false) - } - Mutable::Vec(vec) => { - if let Some(target) = vec.get_mut(index) { - target.clone_from(value); + target.clone_from(from); return VmResult::Ok(true); } @@ -1072,7 +1081,7 @@ impl Vm { _ => return VmResult::Ok(false), }; - target.clone_from(value); + target.clone_from(from); VmResult::Ok(true) } Mutable::Option(option) => { @@ -1081,12 +1090,12 @@ impl Vm { _ => return VmResult::Ok(false), }; - target.clone_from(value); + target.clone_from(from); VmResult::Ok(true) } Mutable::TupleStruct(tuple_struct) => { if let Some(target) = tuple_struct.get_mut(index) { - target.clone_from(value); + target.clone_from(from); return VmResult::Ok(true); } @@ -1095,7 +1104,7 @@ impl Vm { Mutable::Variant(variant) => { if let VariantData::Tuple(data) = variant.data_mut() { if let Some(target) = data.get_mut(index) { - target.clone_from(value); + target.clone_from(from); return VmResult::Ok(true); } } @@ -1104,7 +1113,19 @@ impl Vm { } _ => VmResult::Ok(false), }, - RefRepr::Any(..) => VmResult::Ok(false), + RefRepr::Any(value) => match value.type_hash() { + runtime::Vec::HASH => { + let mut vec = vm_try!(value.borrow_mut::()); + + if let Some(target) = vec.get_mut(index) { + target.clone_from(from); + return VmResult::Ok(true); + } + + VmResult::Ok(false) + } + _ => VmResult::Ok(false), + }, } } @@ -1213,7 +1234,6 @@ impl Vm { }, BorrowRefRepr::Mutable(value) => match (ty, &*value) { (TypeCheck::Tuple, Mutable::Tuple(tuple)) => Some(f(tuple)), - (TypeCheck::Vec, Mutable::Vec(vec)) => Some(f(vec)), (TypeCheck::Result(v), Mutable::Result(result)) => match (v, result) { (0, Ok(ok)) => Some(f(slice::from_ref(ok))), (1, Err(err)) => Some(f(slice::from_ref(err))), @@ -1226,7 +1246,13 @@ impl Vm { }, _ => None, }, - BorrowRefRepr::Any(..) => None, + BorrowRefRepr::Any(value) => match (ty, value.type_hash()) { + (TypeCheck::Vec, runtime::Vec::HASH) => { + let vec = vm_try!(value.borrow_ref::()); + Some(f(&vec)) + } + _ => None, + }, }; VmResult::Ok(value) @@ -3273,7 +3299,6 @@ impl Vm { }, BorrowRefRepr::Mutable(value) => match (type_check, &*value) { (TypeCheck::Tuple, Mutable::Tuple(..)) => true, - (TypeCheck::Vec, Mutable::Vec(..)) => true, (TypeCheck::Result(v), Mutable::Result(result)) => match (v, result) { (0, Ok(..)) => true, (1, Err(..)) => true, @@ -3286,7 +3311,10 @@ impl Vm { }, _ => false, }, - BorrowRefRepr::Any(..) => false, + BorrowRefRepr::Any(value) => match (type_check, value.type_hash()) { + (TypeCheck::Vec, runtime::Vec::HASH) => true, + _ => false, + }, }; vm_try!(out.store(&mut self.stack, is_match)); @@ -3649,7 +3677,7 @@ impl Vm { where F: FnOnce() -> T, { - let _guard = crate::runtime::env::Guard::new(self.context.clone(), self.unit.clone(), None); + let _guard = runtime::env::Guard::new(self.context.clone(), self.unit.clone(), None); f() } @@ -3667,8 +3695,7 @@ impl Vm { // NB: set up environment so that native function can access context and // unit. - let _guard = - crate::runtime::env::Guard::new(self.context.clone(), self.unit.clone(), diagnostics); + let _guard = runtime::env::Guard::new(self.context.clone(), self.unit.clone(), diagnostics); let mut budget = budget::acquire();