diff --git a/crates/rune-macros/src/any.rs b/crates/rune-macros/src/any.rs index 5bd0580c9..450a64b82 100644 --- a/crates/rune-macros/src/any.rs +++ b/crates/rune-macros/src/any.rs @@ -669,32 +669,7 @@ where let type_parameters = quote!(#hash::parameters([#(<#generic_names as #type_hash_t>::HASH),*])); - let impl_type_of = is_generic.is_none().then(|| quote! { - #[automatically_derived] - #(#attrs)* - impl #impl_generics #type_hash_t for #ident #type_generics #where_clause { - const HASH: #hash = #make_hash; - } - - #[automatically_derived] - #(#attrs)* - impl #impl_generics #type_of for #ident #type_generics #where_clause { - const PARAMETERS: #hash = #type_parameters; - const STATIC_TYPE_INFO: #any_type_info = ::ANY_TYPE_INFO; - } - - #[automatically_derived] - #(#attrs)* - impl #impl_generics #maybe_type_of for #ident #type_generics #where_clause { - #[inline] - fn maybe_type_of() -> #alloc::Result<#meta::DocType> { - #meta::DocType::with_generics( - ::HASH, - [#(<#generic_names as #maybe_type_of>::maybe_type_of()?),*] - ) - } - } - + let to_value_impl = quote! { #[automatically_derived] #(#attrs)* impl #impl_generics #unsafe_to_ref for #ident #type_generics #where_clause { @@ -738,6 +713,35 @@ where #vm_result::Ok((shared, guard)) } } + }; + + let impl_type_of = is_generic.is_none().then(|| { + quote! { + #[automatically_derived] + #(#attrs)* + impl #impl_generics #type_hash_t for #ident #type_generics #where_clause { + const HASH: #hash = #make_hash; + } + + #[automatically_derived] + #(#attrs)* + impl #impl_generics #type_of for #ident #type_generics #where_clause { + const PARAMETERS: #hash = #type_parameters; + const STATIC_TYPE_INFO: #any_type_info = ::ANY_TYPE_INFO; + } + + #[automatically_derived] + #(#attrs)* + impl #impl_generics #maybe_type_of for #ident #type_generics #where_clause { + #[inline] + fn maybe_type_of() -> #alloc::Result<#meta::DocType> { + #meta::DocType::with_generics( + ::HASH, + [#(<#generic_names as #maybe_type_of>::maybe_type_of()?),*] + ) + } + } + } }); let impl_any = quote! { @@ -759,6 +763,7 @@ where quote! { #install_with #impl_named + #to_value_impl #impl_type_of #impl_any #impl_non_generic diff --git a/crates/rune/src/cli/tests.rs b/crates/rune/src/cli/tests.rs index 03418e7e1..179552ac1 100644 --- a/crates/rune/src/cli/tests.rs +++ b/crates/rune/src/cli/tests.rs @@ -18,8 +18,8 @@ use crate::cli::{ use crate::compile::FileSourceLoader; use crate::doc::{TestKind, TestParams}; use crate::modules::capture_io::CaptureIo; -use crate::runtime::{Mutable, OwnedRepr, Value, Vm, VmError, VmResult}; -use crate::{Diagnostics, Hash, Item, ItemBuf, Source, Sources, Unit}; +use crate::runtime::{ReprRef, Value, Vm, VmError, VmResult}; +use crate::{Diagnostics, Hash, Item, ItemBuf, Source, Sources, TypeHash, Unit}; mod cli { use std::string::String; @@ -534,14 +534,25 @@ impl TestCase { capture_io.drain_into(&mut self.output)?; self.outcome = match result { - VmResult::Ok(v) => match v.take_repr()? { - OwnedRepr::Mutable(Mutable::Result(result)) => match result { - Ok(..) => Outcome::Ok, - Err(error) => Outcome::Err(error), - }, - OwnedRepr::Mutable(Mutable::Option(option)) => match option { - Some(..) => Outcome::Ok, - None => Outcome::None, + VmResult::Ok(v) => match v.as_ref()? { + ReprRef::Any(value) => match value.type_hash() { + Result::::HASH => { + let result = value.borrow_ref::>()?; + + match &*result { + Ok(..) => Outcome::Ok, + Err(error) => Outcome::Err(error.clone()), + } + } + Option::::HASH => { + let option = value.borrow_ref::>()?; + + match &*option { + Some(..) => Outcome::Ok, + None => Outcome::None, + } + } + _ => Outcome::Ok, }, _ => Outcome::Ok, }, diff --git a/crates/rune/src/compile/ir/eval.rs b/crates/rune/src/compile/ir/eval.rs index 2ddd91f07..30664b073 100644 --- a/crates/rune/src/compile/ir/eval.rs +++ b/crates/rune/src/compile/ir/eval.rs @@ -7,7 +7,7 @@ use crate::ast::{Span, Spanned}; use crate::compile::ir::{self}; use crate::compile::{self, WithSpan}; use crate::query::Used; -use crate::runtime::{BorrowRefRepr, Inline, Object, OwnedTuple, Value}; +use crate::runtime::{Inline, Object, OwnedTuple, ReprRef, Value}; use crate::TypeHash; /// The outcome of a constant evaluation. @@ -72,11 +72,11 @@ fn eval_ir_binary( let a = eval_ir(&ir.lhs, interp, used)?; let b = eval_ir(&ir.rhs, interp, used)?; - let a = a.borrow_ref_repr().with_span(ir)?; - let b = b.borrow_ref_repr().with_span(ir)?; + let a = a.as_ref().with_span(ir)?; + let b = b.as_ref().with_span(ir)?; match (a, b) { - (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { + (ReprRef::Inline(a), ReprRef::Inline(b)) => { let out = 'out: { match (a, b) { (Inline::Signed(a), Inline::Signed(b)) => match ir.op { @@ -140,7 +140,7 @@ fn eval_ir_binary( return Ok(Value::from(out)); } - (BorrowRefRepr::Any(a), BorrowRefRepr::Any(b)) => { + (ReprRef::Any(a), ReprRef::Any(b)) => { let value = 'out: { if let (String::HASH, String::HASH) = (a.type_hash(), b.type_hash()) { let a = a.borrow_ref::().with_span(span)?; @@ -353,10 +353,10 @@ fn eval_ir_template( } ir::IrTemplateComponent::Ir(ir) => { let const_value = eval_ir(ir, interp, used)?; - let value = const_value.borrow_ref_repr().with_span(ir)?; + let value = const_value.as_ref().with_span(ir)?; match value { - BorrowRefRepr::Inline(value) => match value { + ReprRef::Inline(value) => match value { Inline::Signed(integer) => { write!(buf, "{integer}")?; } @@ -371,7 +371,7 @@ fn eval_ir_template( return Err(EvalOutcome::not_const(ir)); } }, - BorrowRefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = value.borrow_ref::().with_span(ir)?; buf.try_push_str(&s)?; @@ -380,7 +380,7 @@ fn eval_ir_template( return Err(EvalOutcome::not_const(ir)); } }, - BorrowRefRepr::Mutable(..) => { + ReprRef::Mutable(..) => { return Err(EvalOutcome::not_const(ir)); } } diff --git a/crates/rune/src/compile/ir/interpreter.rs b/crates/rune/src/compile/ir/interpreter.rs index d5ab55064..c9a67c8e1 100644 --- a/crates/rune/src/compile/ir/interpreter.rs +++ b/crates/rune/src/compile/ir/interpreter.rs @@ -7,7 +7,7 @@ use crate::compile::meta; use crate::compile::{self, IrErrorKind, ItemId, ModId, WithSpan}; use crate::hir; use crate::query::{Query, Used}; -use crate::runtime::{self, ConstValue, Object, OwnedTuple, RefRepr, Value}; +use crate::runtime::{self, ConstValue, Object, OwnedTuple, ReprRef, Value}; use crate::TypeHash; /// The interpreter that executed [Ir][crate::ir::Ir]. @@ -200,22 +200,22 @@ impl ir::Scopes { } ir::IrTargetKind::Index(target, index) => { let value = self.get_target(target)?; - let target = value.as_ref_repr().with_span(ir_target)?; + let target = value.as_ref().with_span(ir_target)?; match target { - RefRepr::Inline(value) => { + ReprRef::Inline(value) => { return Err(compile::Error::expected_type::( ir_target, value.type_info(), )); } - RefRepr::Mutable(value) => { + ReprRef::Mutable(value) => { return Err(compile::Error::expected_type::( ir_target, value.borrow_ref().with_span(ir_target)?.type_info(), )); } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { runtime::Vec::HASH => { let vec = value.borrow_ref::().with_span(ir_target)?; @@ -270,14 +270,14 @@ impl ir::Scopes { ir::IrTargetKind::Index(target, index) => { let target = self.get_target(target)?; - match target.as_ref_repr().with_span(ir_target)? { - RefRepr::Inline(value) => { + match target.as_ref().with_span(ir_target)? { + ReprRef::Inline(value) => { return Err(compile::Error::expected_type::( ir_target, value.type_info(), )); } - RefRepr::Mutable(current) => { + ReprRef::Mutable(current) => { let mutable = current.borrow_mut().with_span(ir_target)?; return Err(compile::Error::expected_type::( @@ -285,7 +285,7 @@ impl ir::Scopes { mutable.type_info(), )); } - RefRepr::Any(any) => match any.type_hash() { + ReprRef::Any(any) => match any.type_hash() { runtime::Vec::HASH => { let mut vec = any.borrow_mut::().with_span(ir_target)?; @@ -347,8 +347,8 @@ impl ir::Scopes { ir::IrTargetKind::Index(target, index) => { let current = self.get_target(target)?; - match current.as_ref_repr().with_span(ir_target)? { - RefRepr::Mutable(value) => { + match current.as_ref().with_span(ir_target)? { + ReprRef::Mutable(value) => { let value = value.borrow_ref().with_span(ir_target)?; Err(compile::Error::expected_type::( @@ -356,7 +356,7 @@ impl ir::Scopes { value.type_info(), )) } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { runtime::Vec::HASH => { let mut vec = value.borrow_mut::().with_span(ir_target)?; diff --git a/crates/rune/src/internal_macros.rs b/crates/rune/src/internal_macros.rs index e6165c61f..73648b198 100644 --- a/crates/rune/src/internal_macros.rs +++ b/crates/rune/src/internal_macros.rs @@ -87,48 +87,6 @@ macro_rules! cfg_std { } } -macro_rules! from_value_ref { - ($ty:ty, $into_ref:ident, $into_mut:ident) => { - impl $crate::runtime::UnsafeToRef for $ty { - type Guard = $crate::runtime::RawAnyGuard; - - unsafe fn unsafe_to_ref<'a>( - value: $crate::runtime::Value, - ) -> $crate::runtime::VmResult<(&'a Self, Self::Guard)> { - let value = vm_try!(value.$into_ref()); - let (value, guard) = $crate::runtime::Ref::into_raw(value); - $crate::runtime::VmResult::Ok((value.as_ref(), guard)) - } - } - - impl $crate::runtime::UnsafeToMut for $ty { - type Guard = $crate::runtime::RawAnyGuard; - - unsafe fn unsafe_to_mut<'a>( - value: $crate::runtime::Value, - ) -> $crate::runtime::VmResult<(&'a mut Self, Self::Guard)> { - let value = vm_try!(value.$into_mut()); - let (mut value, guard) = $crate::runtime::Mut::into_raw(value); - $crate::runtime::VmResult::Ok((value.as_mut(), guard)) - } - } - - impl $crate::runtime::FromValue for $crate::runtime::Ref<$ty> { - fn from_value(value: Value) -> Result { - let value = value.$into_ref()?; - Ok(value) - } - } - - impl $crate::runtime::FromValue for $crate::runtime::Mut<$ty> { - fn from_value(value: Value) -> Result { - let value = value.$into_mut()?; - Ok(value) - } - } - }; -} - macro_rules! impl_builtin_type_of { ( $( diff --git a/crates/rune/src/lib.rs b/crates/rune/src/lib.rs index cd2ae8f7b..c399617c0 100644 --- a/crates/rune/src/lib.rs +++ b/crates/rune/src/lib.rs @@ -255,8 +255,8 @@ pub mod query; pub mod runtime; #[doc(inline)] pub use self::runtime::{ - from_const_value, from_value, to_const_value, to_value, FromValue, ToConstValue, ToValue, - TypeHash, Unit, Value, Vm, + from_const_value, from_value, to_const_value, to_value, FromValue, Mut, Ref, ToConstValue, + ToValue, TypeHash, Unit, Value, Vm, }; mod shared; @@ -682,7 +682,6 @@ mod tests; rune_macros::binding! { #[generic] impl ::std::option::Option for Option; - #[generic] impl ::std::result::Result for Result; @@ -763,6 +762,3 @@ impl_builtin_type_of! { impl ::std::any::Type, crate::runtime::Type; } - -from_value_ref!(Result, into_result_ref, into_result_mut); -from_value_ref!(Option, into_option_ref, into_option_mut); diff --git a/crates/rune/src/macros/format_args.rs b/crates/rune/src/macros/format_args.rs index d616ceb76..95985bd1c 100644 --- a/crates/rune/src/macros/format_args.rs +++ b/crates/rune/src/macros/format_args.rs @@ -48,7 +48,7 @@ impl FormatArgs { } } - let format = format.into_any::().with_span(&self.format)?; + let format = format.downcast::().with_span(&self.format)?; let mut unused_pos = (0..pos.len()).try_collect::>()?; let mut unused_named = named diff --git a/crates/rune/src/module/module.rs b/crates/rune/src/module/module.rs index baaabb684..75cc4e9ed 100644 --- a/crates/rune/src/module/module.rs +++ b/crates/rune/src/module/module.rs @@ -733,8 +733,7 @@ impl Module { /// # Examples /// /// ``` - /// use rune::{Module, ContextError}; - /// use rune::runtime::Ref; + /// use rune::{ContextError, Module, Ref}; /// /// /// This is a pretty neat function. /// #[rune::function] @@ -759,8 +758,7 @@ impl Module { /// Registering instance functions: /// /// ``` - /// use rune::{Any, Module}; - /// use rune::runtime::Ref; + /// use rune::{Any, Module, Ref}; /// /// #[derive(Any)] /// struct MyBytes { @@ -1063,8 +1061,7 @@ impl Module { /// use std::sync::atomic::AtomicU32; /// use std::sync::Arc; /// - /// use rune::{Any, Module}; - /// use rune::runtime::Ref; + /// use rune::{Any, Module, Ref}; /// /// #[derive(Clone, Debug, Any)] /// struct Client { diff --git a/crates/rune/src/modules/bytes.rs b/crates/rune/src/modules/bytes.rs index 0308afeba..55cdbc1c7 100644 --- a/crates/rune/src/modules/bytes.rs +++ b/crates/rune/src/modules/bytes.rs @@ -415,7 +415,7 @@ fn cmp(this: &[u8], rhs: &[u8]) -> Ordering { this.cmp(rhs) } -/// Hash the string. +/// Hash the byte array. /// /// # Examples /// diff --git a/crates/rune/src/modules/future.rs b/crates/rune/src/modules/future.rs index 8809370f4..ae2ab0495 100644 --- a/crates/rune/src/modules/future.rs +++ b/crates/rune/src/modules/future.rs @@ -2,7 +2,7 @@ use crate as rune; use crate::alloc::Vec; -use crate::runtime::{self, Future, Inline, RefRepr, SelectFuture, Value, VmErrorKind, VmResult}; +use crate::runtime::{self, Future, Inline, ReprRef, SelectFuture, Value, VmErrorKind, VmResult}; use crate::{ContextError, Module, TypeHash}; /// Asynchronous computations. @@ -25,20 +25,20 @@ where let mut results = vm_try!(Vec::try_with_capacity(len)); for (index, value) in values.into_iter().enumerate() { - match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(value) => { + match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => { return VmResult::err([ VmErrorKind::expected::(value.type_info()), VmErrorKind::bad_argument(index), ]); } - RefRepr::Mutable(value) => { + ReprRef::Mutable(value) => { return VmResult::err([ VmErrorKind::expected::(vm_try!(value.borrow_ref()).type_info()), VmErrorKind::bad_argument(index), ]); } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { Future::HASH => { let future = vm_try!(Value::from(value.clone()).into_future()); futures.push(SelectFuture::new(index, future)); @@ -98,19 +98,19 @@ where /// ``` #[rune::function(keep)] async fn join(value: Value) -> VmResult { - match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(value) => match value { + match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Unit => VmResult::Ok(Value::unit()), value => VmResult::err([ VmErrorKind::bad_argument(0), VmErrorKind::expected::(value.type_info()), ]), }, - RefRepr::Mutable(value) => VmResult::err([ + ReprRef::Mutable(value) => VmResult::err([ VmErrorKind::bad_argument(0), VmErrorKind::expected::(vm_try!(value.borrow_ref()).type_info()), ]), - RefRepr::Any(value) => match value.type_hash() { + ReprRef::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| { diff --git a/crates/rune/src/modules/iter.rs b/crates/rune/src/modules/iter.rs index fa93b4f36..d164ef4a9 100644 --- a/crates/rune/src/modules/iter.rs +++ b/crates/rune/src/modules/iter.rs @@ -8,7 +8,7 @@ use crate::modules::collections::VecDeque; use crate::modules::collections::{HashMap, HashSet}; use crate::runtime::range::RangeIter; use crate::runtime::{ - BorrowRefRepr, FromValue, Function, Inline, InstAddress, Object, Output, OwnedTuple, Protocol, + FromValue, Function, Inline, InstAddress, Object, Output, OwnedTuple, Protocol, ReprRef, TypeHash, Value, Vec, VmErrorKind, VmResult, }; use crate::shared::Caller; @@ -473,17 +473,19 @@ pub fn module() -> Result { let mut string = String::new(); while let Some(value) = vm_try!(next.call((iter.clone(),))) { - match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(Inline::Char(c)) => { + match vm_try!(value.as_ref()) { + ReprRef::Inline(Inline::Char(c)) => { vm_try!(string.try_push(*c)); } - BorrowRefRepr::Inline(value) => { + ReprRef::Inline(value) => { return VmResult::expected::(value.type_info()); } - BorrowRefRepr::Mutable(value) => { - return VmResult::expected::(value.type_info()); + ReprRef::Mutable(value) => { + return VmResult::expected::( + vm_try!(value.borrow_ref()).type_info(), + ); } - BorrowRefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); vm_try!(string.try_push_str(&s)); diff --git a/crates/rune/src/modules/option.rs b/crates/rune/src/modules/option.rs index d6cd13542..9868903eb 100644 --- a/crates/rune/src/modules/option.rs +++ b/crates/rune/src/modules/option.rs @@ -1,9 +1,14 @@ //! The [`Option`] type. +use core::cmp::Ordering; +use core::hash::Hasher as _; + use crate as rune; +use crate::alloc::fmt::TryWrite; use crate::alloc::String; use crate::runtime::{ - ControlFlow, Formatter, Function, Panic, Protocol, RuntimeError, Value, VmResult, + ControlFlow, EnvProtocolCaller, Formatter, Function, Hasher, Panic, Protocol, RuntimeError, + Value, VmResult, }; use crate::Any; use crate::{ContextError, Module}; @@ -59,6 +64,25 @@ pub fn module() -> Result { m.function_meta(unwrap_or_else)?; m.function_meta(ok_or)?; m.function_meta(ok_or_else)?; + + m.function_meta(clone__meta)?; + m.implement_trait::>(rune::item!(::std::clone::Clone))?; + + m.function_meta(partial_eq__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::PartialEq))?; + + m.function_meta(eq__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::Eq))?; + + m.function_meta(partial_cmp__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::PartialOrd))?; + + m.function_meta(cmp__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::Ord))?; + + m.function_meta(hash__meta)?; + m.function_meta(debug_fmt__meta)?; + m.function_meta(option_try__meta)?; m.ty::()?; @@ -67,6 +91,8 @@ pub fn module() -> Result { m.function_meta(Iter::size_hint__meta)?; m.implement_trait::(rune::item!(::std::iter::Iterator))?; m.implement_trait::(rune::item!(::std::iter::DoubleEndedIterator))?; + m.function_meta(Iter::clone__meta)?; + m.implement_trait::(rune::item!(::std::clone::Clone))?; Ok(m) } @@ -303,7 +329,7 @@ fn transpose(this: &Option) -> VmResult { } }; - match &*vm_try!(value.borrow_result_ref()) { + match &*vm_try!(value.borrow_ref::>()) { Ok(ok) => { let some = vm_try!(Value::try_from(Some(ok.clone()))); let result = vm_try!(Value::try_from(Ok(some))); @@ -441,6 +467,186 @@ fn ok_or_else(this: &Option, err: Function) -> VmResult) -> VmResult> { + VmResult::Ok(match this { + Some(value) => Some(vm_try!(value.clone_with(&mut EnvProtocolCaller))), + None => None, + }) +} + +/// Test two options for partial equality. +/// +/// # Examples +/// +/// ```rune +/// assert!(None == None); +/// assert!(Some(b"a") == Some(b"a")); +/// assert!(Some(b"a") != Some(b"ab")); +/// assert!(Some(b"ab") != Some(b"a")); +/// ``` +/// +/// Using explicit functions: +/// +/// ```rune +/// use std::ops::partial_eq; +/// +/// assert_eq!(partial_eq(None, None), true); +/// assert_eq!(partial_eq(Some(b"a"), Some(b"a")), true); +/// assert_eq!(partial_eq(Some(b"a"), Some(b"ab")), false); +/// assert_eq!(partial_eq(Some(b"ab"), Some(b"a")), false); +/// ``` +#[rune::function(keep, instance, protocol = PARTIAL_EQ)] +#[inline] +fn partial_eq(this: &Option, rhs: &Option) -> VmResult { + match (this, rhs) { + (Some(a), Some(b)) => Value::partial_eq(a, b), + (None, None) => VmResult::Ok(true), + _ => VmResult::Ok(false), + } +} + +/// Test two options for total equality. +/// +/// # Examples +/// +/// ```rune +/// use std::ops::eq; +/// +/// assert_eq!(eq(None, None), true); +/// assert_eq!(eq(Some(b"a"), Some(b"a")), true); +/// assert_eq!(eq(Some(b"a"), Some(b"ab")), false); +/// assert_eq!(eq(Some(b"ab"), Some(b"a")), false); +/// ``` +#[rune::function(keep, instance, protocol = EQ)] +#[inline] +fn eq(this: &Option, rhs: &Option) -> VmResult { + match (this, rhs) { + (Some(a), Some(b)) => Value::eq(a, b), + (None, None) => VmResult::Ok(true), + _ => VmResult::Ok(false), + } +} + +/// Perform a partial ordered comparison between two options. +/// +/// # Examples +/// +/// ```rune +/// assert!(Some(b"a") < Some(b"ab")); +/// assert!(Some(b"ab") > Some(b"a")); +/// assert!(Some(b"a") == Some(b"a")); +/// ``` +/// +/// Using explicit functions: +/// +/// ```rune +/// use std::cmp::Ordering; +/// use std::ops::partial_cmp; +/// +/// assert_eq!(partial_cmp(Some(b"a"), Some(b"ab")), Some(Ordering::Less)); +/// assert_eq!(partial_cmp(Some(b"ab"), Some(b"a")), Some(Ordering::Greater)); +/// assert_eq!(partial_cmp(Some(b"a"), Some(b"a")), Some(Ordering::Equal)); +/// ``` +#[rune::function(keep, instance, protocol = PARTIAL_CMP)] +#[inline] +fn partial_cmp(this: &Option, rhs: &Option) -> VmResult> { + match (this, rhs) { + (Some(a), Some(b)) => Value::partial_cmp(a, b), + (None, None) => VmResult::Ok(Some(Ordering::Equal)), + (Some(..), None) => VmResult::Ok(Some(Ordering::Greater)), + (None, Some(..)) => VmResult::Ok(Some(Ordering::Less)), + } +} + +/// Perform a totally ordered comparison between two options. +/// +/// # Examples +/// +/// ```rune +/// use std::cmp::Ordering; +/// use std::ops::cmp; +/// +/// assert_eq!(cmp(Some(b"a"), Some(b"ab")), Ordering::Less); +/// assert_eq!(cmp(Some(b"ab"), Some(b"a")), Ordering::Greater); +/// assert_eq!(cmp(Some(b"a"), Some(b"a")), Ordering::Equal); +/// ``` +#[rune::function(keep, instance, protocol = CMP)] +#[inline] +fn cmp(this: &Option, rhs: &Option) -> VmResult { + match (this, rhs) { + (Some(a), Some(b)) => Value::cmp(a, b), + (None, None) => VmResult::Ok(Ordering::Equal), + (Some(..), None) => VmResult::Ok(Ordering::Greater), + (None, Some(..)) => VmResult::Ok(Ordering::Less), + } +} + +/// Hash the result. +/// +/// # Examples +/// +/// ```rune +/// use std::ops::hash; +/// +/// let a = Ok("hello"); +/// let b = Ok("hello"); +/// +/// assert_eq!(hash(a), hash(b)); +/// ``` +#[rune::function(keep, instance, protocol = HASH)] +fn hash(this: &Option, hasher: &mut Hasher) -> VmResult<()> { + match this { + Some(value) => { + hasher.write_u64(0); + vm_try!(value.hash(hasher)); + } + None => { + hasher.write_u64(1); + } + } + + VmResult::Ok(()) +} + +/// Write a debug representation of a result. +/// +/// # Examples +/// +/// ```rune +/// println!("{:?}", Some("Hello")); +/// println!("{:?}", None); +/// ``` +#[rune::function(keep, instance, protocol = DEBUG_FMT)] +#[inline] +fn debug_fmt(this: &Option, f: &mut Formatter) -> VmResult<()> { + match this { + Some(value) => { + vm_try!(f.try_write_str("Some(")); + vm_try!(value.debug_fmt(f)); + vm_try!(f.try_write_str(")")); + } + None => { + vm_try!(f.try_write_str("None")); + } + } + + VmResult::Ok(()) +} + /// Using [`Option`] with the try protocol. /// /// # Examples @@ -461,7 +667,7 @@ pub(crate) fn option_try(this: &Option) -> VmResult { }) } -#[derive(Any)] +#[derive(Any, Clone)] #[rune(item = ::std::option)] pub(crate) struct Iter { value: Option, @@ -474,18 +680,44 @@ impl Iter { } /// Get the next value in the iterator. + /// + /// # Examples + /// + /// ```rune + /// let a = Some(1).iter(); + /// + /// assert_eq!(a.next(), Some(1)); + /// assert_eq!(a.next(), None); + /// ``` #[rune::function(keep, protocol = NEXT)] fn next(&mut self) -> Option { self.value.take() } /// Get the next back value in the iterator. + /// + /// # Examples + /// + /// ```rune + /// let a = Some(1).iter(); + /// + /// assert_eq!(a.next_back(), Some(1)); + /// assert_eq!(a.next_back(), None); + /// ``` #[rune::function(keep, protocol = NEXT_BACK)] fn next_back(&mut self) -> Option { self.value.take() } - /// Get the size hint. + /// Get a size hint of the option iterator. + /// + /// # Examples + /// + /// ```rune + /// let a = Some(1).iter(); + /// + /// assert_eq!(a.size_hint(), (1, Some(1))); + /// ``` #[rune::function(keep, protocol = SIZE_HINT)] fn size_hint(&self) -> (usize, Option) { let len = usize::from(self.value.is_some()); @@ -493,8 +725,40 @@ impl Iter { } /// Convert into an iterator. + /// + /// # Examples + /// + /// ```rune + /// let a = Some(42); + /// + /// let v = 0; + /// + /// for i in a { + /// v = 42; + /// } + /// + /// assert_eq!(v, 1); + /// ``` #[rune::function(keep, protocol = INTO_ITER)] fn into_iter(self) -> Self { self } + + /// Clone the option iterator. + /// + /// # Examples + /// + /// ```rune + /// let a = Some(1); + /// let it = a.iter(); + /// + /// assert_eq!(it.clone().next(), Some(1)); + /// assert_eq!(it.next(), Some(1)); + /// assert_eq!(it.next(), None); + /// ``` + #[rune::function(keep, protocol = CLONE)] + #[inline] + fn clone(&self) -> Self { + Clone::clone(self) + } } diff --git a/crates/rune/src/modules/result.rs b/crates/rune/src/modules/result.rs index 4b2a5db0a..984ef772f 100644 --- a/crates/rune/src/modules/result.rs +++ b/crates/rune/src/modules/result.rs @@ -1,9 +1,14 @@ //! The [`Result`] type. +use core::cmp::Ordering; +use core::hash::Hasher as _; + use crate as rune; use crate::alloc::fmt::TryWrite; use crate::alloc::prelude::*; -use crate::runtime::{ControlFlow, Formatter, Function, Panic, Protocol, Value, VmResult}; +use crate::runtime::{ + ControlFlow, EnvProtocolCaller, Formatter, Function, Hasher, Panic, Protocol, Value, VmResult, +}; use crate::{ContextError, Module}; /// The [`Result`] type. @@ -11,10 +16,10 @@ use crate::{ContextError, Module}; /// This module deals with the fundamental [`Result`] type in Rune. #[rune::module(::std::result)] pub fn module() -> Result { - let mut module = Module::from_meta(self::module_meta)?; + let mut m = Module::from_meta(self::module_meta)?; // Sorted for ease of finding - let mut result = module + let mut result = m .ty::>()? .static_docs(&["Result is a type that represents either success (Ok) or failure (Err)."])? .make_enum(&["Ok", "Err"])?; @@ -31,7 +36,7 @@ pub fn module() -> Result { .constructor(Result::Err)? .static_docs(&["Contains the error value"])?; - module.associated_function( + m.associated_function( Protocol::IS_VARIANT, |this: &Result, index: usize| match (this, index) { (Result::Ok(_), 0) => true, @@ -40,28 +45,54 @@ pub fn module() -> Result { }, )?; - module.index_function(Protocol::GET, 0, |this: &Result| match this { + m.index_function(Protocol::GET, 0, |this: &Result| match this { Result::Ok(value) => VmResult::Ok(value.clone()), Result::Err(value) => VmResult::Ok(value.clone()), })?; - module.function_meta(ok)?; - module.function_meta(is_ok)?; - module.function_meta(is_err)?; - module.function_meta(unwrap)?; - module.function_meta(unwrap_or)?; - module.function_meta(unwrap_or_else)?; - module.function_meta(expect)?; - module.function_meta(and_then)?; - module.function_meta(map)?; - module.function_meta(result_try__meta)?; - Ok(module) + m.function_meta(ok)?; + m.function_meta(is_ok)?; + m.function_meta(is_err)?; + m.function_meta(unwrap)?; + m.function_meta(unwrap_or)?; + m.function_meta(unwrap_or_else)?; + m.function_meta(expect)?; + m.function_meta(and_then)?; + m.function_meta(map)?; + + m.function_meta(clone__meta)?; + m.implement_trait::>(rune::item!(::std::clone::Clone))?; + + m.function_meta(partial_eq__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::PartialEq))?; + + m.function_meta(eq__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::Eq))?; + + m.function_meta(partial_cmp__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::PartialOrd))?; + + m.function_meta(cmp__meta)?; + m.implement_trait::>(rune::item!(::std::cmp::Ord))?; + + m.function_meta(hash__meta)?; + m.function_meta(debug_fmt__meta)?; + + m.function_meta(result_try__meta)?; + Ok(m) } -/// Converts from `Result` to `Option`. +/// Converts from `Result` to `Option`. +/// +/// # Examples +/// +/// ```rune +/// let a = Ok(2); +/// let b = Err(3); /// -/// Converts self into an `Option`, consuming `self`, and discarding the -/// error, if any. +/// assert_eq!(a.ok(), Some(2)); +/// assert_eq!(b.ok(), None); +/// ``` #[rune::function(instance)] fn ok(result: &Result) -> Option { result.as_ref().ok().cloned() @@ -286,6 +317,189 @@ fn map(this: &Result, then: Function) -> VmResult) -> VmResult> { + VmResult::Ok(match this { + Ok(ok) => Ok(vm_try!(ok.clone_with(&mut EnvProtocolCaller))), + Err(err) => Err(vm_try!(err.clone_with(&mut EnvProtocolCaller))), + }) +} + +/// Test two results for partial equality. +/// +/// # Examples +/// +/// ```rune +/// assert_eq!(Ok(b"a") == Ok(b"a"), true); +/// assert_eq!(Ok(b"a") == Ok(b"ab"), false); +/// assert_eq!(Ok(b"ab") == Ok(b"a"), false); +/// ``` +/// +/// Using explicit functions: +/// +/// ```rune +/// use std::ops::partial_eq; +/// +/// assert_eq!(partial_eq(Ok(b"a"), Ok(b"a")), true); +/// assert_eq!(partial_eq(Ok(b"a"), Ok(b"ab")), false); +/// assert_eq!(partial_eq(Ok(b"ab"), Ok(b"a")), false); +/// ``` +#[rune::function(keep, instance, protocol = PARTIAL_EQ)] +#[inline] +fn partial_eq(this: &Result, rhs: &Result) -> VmResult { + match (this, rhs) { + (Ok(a), Ok(b)) => Value::partial_eq(a, b), + (Err(a), Err(b)) => Value::partial_eq(a, b), + _ => VmResult::Ok(false), + } +} + +/// Test two results for total equality. +/// +/// # Examples +/// +/// ```rune +/// use std::ops::eq; +/// +/// assert_eq!(eq(Ok(b"a"), Ok(b"a")), true); +/// assert_eq!(eq(Ok(b"a"), Ok(b"ab")), false); +/// assert_eq!(eq(Ok(b"ab"), Ok(b"a")), false); +/// ``` +#[rune::function(keep, instance, protocol = EQ)] +#[inline] +fn eq(this: &Result, rhs: &Result) -> VmResult { + match (this, rhs) { + (Ok(a), Ok(b)) => Value::eq(a, b), + (Err(a), Err(b)) => Value::eq(a, b), + _ => VmResult::Ok(false), + } +} + +/// Perform a partial ordered comparison between two results. +/// +/// # Examples +/// +/// ```rune +/// assert!(Ok(b"a") < Ok(b"ab")); +/// assert!(Ok(b"ab") > Ok(b"a")); +/// assert!(Ok(b"a") == Ok(b"a")); +/// ``` +/// +/// Using explicit functions: +/// +/// ```rune +/// use std::cmp::Ordering; +/// use std::ops::partial_cmp; +/// +/// assert_eq!(partial_cmp(Ok(b"a"), Ok(b"ab")), Some(Ordering::Less)); +/// assert_eq!(partial_cmp(Ok(b"ab"), Ok(b"a")), Some(Ordering::Greater)); +/// assert_eq!(partial_cmp(Ok(b"a"), Ok(b"a")), Some(Ordering::Equal)); +/// ``` +#[rune::function(keep, instance, protocol = PARTIAL_CMP)] +#[inline] +fn partial_cmp( + this: &Result, + rhs: &Result, +) -> VmResult> { + match (this, rhs) { + (Ok(a), Ok(b)) => Value::partial_cmp(a, b), + (Err(a), Err(b)) => Value::partial_cmp(a, b), + (Ok(..), Err(..)) => VmResult::Ok(Some(Ordering::Greater)), + (Err(..), Ok(..)) => VmResult::Ok(Some(Ordering::Less)), + } +} + +/// Perform a totally ordered comparison between two results. +/// +/// # Examples +/// +/// ```rune +/// use std::cmp::Ordering; +/// use std::ops::cmp; +/// +/// assert_eq!(cmp(Ok(b"a"), Ok(b"ab")), Ordering::Less); +/// assert_eq!(cmp(Ok(b"ab"), Ok(b"a")), Ordering::Greater); +/// assert_eq!(cmp(Ok(b"a"), Ok(b"a")), Ordering::Equal); +/// ``` +#[rune::function(keep, instance, protocol = CMP)] +#[inline] +fn cmp(this: &Result, rhs: &Result) -> VmResult { + match (this, rhs) { + (Ok(a), Ok(b)) => Value::cmp(a, b), + (Err(a), Err(b)) => Value::cmp(a, b), + (Ok(..), Err(..)) => VmResult::Ok(Ordering::Greater), + (Err(..), Ok(..)) => VmResult::Ok(Ordering::Less), + } +} + +/// Hash the result. +/// +/// # Examples +/// +/// ```rune +/// use std::ops::hash; +/// +/// let a = Ok("hello"); +/// let b = Ok("hello"); +/// +/// assert_eq!(hash(a), hash(b)); +/// ``` +#[rune::function(keep, instance, protocol = HASH)] +fn hash(this: &Result, hasher: &mut Hasher) -> VmResult<()> { + match this { + Ok(value) => { + hasher.write_u64(0); + vm_try!(value.hash(hasher)); + } + Err(value) => { + hasher.write_u64(1); + vm_try!(value.hash(hasher)); + } + } + + VmResult::Ok(()) +} + +/// Write a debug representation of a result. +/// +/// # Examples +/// +/// ```rune +/// println!("{:?}", Ok("Hello")); +/// println!("{:?}", Err("Hello")); +/// ``` +#[rune::function(keep, instance, protocol = DEBUG_FMT)] +#[inline] +fn debug_fmt(this: &Result, f: &mut Formatter) -> VmResult<()> { + match this { + Ok(value) => { + vm_try!(f.try_write_str("Ok(")); + vm_try!(value.debug_fmt(f)); + vm_try!(f.try_write_str(")")); + } + Err(value) => { + vm_try!(f.try_write_str("Err(")); + vm_try!(value.debug_fmt(f)); + vm_try!(f.try_write_str(")")); + } + } + + VmResult::Ok(()) +} + /// Using [`Result`] with the try protocol. /// /// # Examples diff --git a/crates/rune/src/modules/string.rs b/crates/rune/src/modules/string.rs index af2643f93..953620ba0 100644 --- a/crates/rune/src/modules/string.rs +++ b/crates/rune/src/modules/string.rs @@ -12,7 +12,7 @@ use crate::alloc::{String, Vec}; use crate::compile::Named; use crate::runtime::{ Bytes, Formatter, FromValue, Function, Hasher, Inline, MaybeTypeOf, Panic, Range, RangeFrom, - RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Ref, RefRepr, ToValue, TypeOf, Value, + RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Ref, ReprRef, ToValue, TypeOf, Value, VmErrorKind, VmResult, }; use crate::{Any, ContextError, Module, TypeHash}; @@ -888,19 +888,19 @@ fn shrink_to_fit(s: &mut String) -> VmResult<()> { /// [`split_whitespace`]: str::split_whitespace #[rune::function(instance, deprecated = "Use String::split instead")] fn split(this: Ref, value: Value) -> VmResult { - match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(Inline::Char(c)) => { + match vm_try!(value.as_ref()) { + ReprRef::Inline(Inline::Char(c)) => { VmResult::Ok(vm_try!(rune::to_value(Split::new(this, *c)))) } - RefRepr::Inline(value) => VmResult::err([ + ReprRef::Inline(value) => VmResult::err([ VmErrorKind::expected::(value.type_info()), VmErrorKind::bad_argument(0), ]), - RefRepr::Mutable(value) => VmResult::err([ + ReprRef::Mutable(value) => VmResult::err([ VmErrorKind::expected::(vm_try!(value.borrow_ref()).type_info()), VmErrorKind::bad_argument(0), ]), - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); @@ -937,21 +937,21 @@ fn split(this: Ref, value: Value) -> VmResult { /// ``` #[rune::function(instance)] fn split_once(this: &str, value: Value) -> VmResult> { - let outcome = match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(Inline::Char(pat)) => this.split_once(*pat), - RefRepr::Inline(value) => { + let outcome = match vm_try!(value.as_ref()) { + ReprRef::Inline(Inline::Char(pat)) => this.split_once(*pat), + ReprRef::Inline(value) => { return VmResult::err([ VmErrorKind::expected::(value.type_info()), VmErrorKind::bad_argument(0), ]); } - RefRepr::Mutable(value) => { + ReprRef::Mutable(value) => { return VmResult::err([ VmErrorKind::expected::(vm_try!(value.borrow_ref()).type_info()), VmErrorKind::bad_argument(0), ]); } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); this.split_once(s.as_str()) diff --git a/crates/rune/src/runtime/bytes.rs b/crates/rune/src/runtime/bytes.rs index fb1e67a11..fe21308bf 100644 --- a/crates/rune/src/runtime/bytes.rs +++ b/crates/rune/src/runtime/bytes.rs @@ -358,7 +358,7 @@ impl UnsafeToRef for [u8] { type Guard = RawAnyGuard; unsafe fn unsafe_to_ref<'a>(value: Value) -> VmResult<(&'a Self, Self::Guard)> { - let (value, guard) = Ref::into_raw(vm_try!(value.into_any_ref::())); + let (value, guard) = Ref::into_raw(vm_try!(value.into_ref::())); VmResult::Ok((value.as_ref().as_slice(), guard)) } } diff --git a/crates/rune/src/runtime/const_value.rs b/crates/rune/src/runtime/const_value.rs index ae8f1a2f0..26e9d5c14 100644 --- a/crates/rune/src/runtime/const_value.rs +++ b/crates/rune/src/runtime/const_value.rs @@ -16,8 +16,8 @@ use crate::runtime; use crate::{Hash, TypeHash}; use super::{ - BorrowRefRepr, Bytes, FromValue, Inline, Mutable, Object, OwnedTuple, ToValue, Tuple, Type, - TypeInfo, Value, VmErrorKind, + Bytes, FromValue, Inline, Object, OwnedTuple, ReprRef, ToValue, Tuple, Type, TypeInfo, Value, + VmErrorKind, }; /// Derive for the [`ToConstValue`](trait@ToConstValue) trait. @@ -234,20 +234,22 @@ impl ConstValue { /// Construct a constant value from a reference to a value.. pub(crate) fn from_value_ref(value: &Value) -> Result { - let inner = match value.borrow_ref_repr()? { - BorrowRefRepr::Inline(value) => ConstValueKind::Inline(*value), - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Option(option) => ConstValueKind::Option(match option { - Some(some) => Some(Box::try_new(Self::from_value_ref(some)?)?), - None => None, - }), - value => { - return Err(RuntimeError::from(VmErrorKind::ConstNotSupported { - actual: value.type_info(), - })) + let inner = match value.as_ref()? { + ReprRef::Inline(value) => ConstValueKind::Inline(*value), + ReprRef::Mutable(value) => { + return Err(RuntimeError::from(VmErrorKind::ConstNotSupported { + actual: value.borrow_ref()?.type_info(), + })); + } + ReprRef::Any(value) => match value.type_hash() { + Option::::HASH => { + let option = value.borrow_ref::>()?; + + ConstValueKind::Option(match &*option { + Some(some) => Some(Box::try_new(Self::from_value_ref(some)?)?), + None => None, + }) } - }, - BorrowRefRepr::Any(value) => match value.type_hash() { String::HASH => { let s = value.borrow_ref::()?; ConstValueKind::String(s.try_to_owned()?) diff --git a/crates/rune/src/runtime/format.rs b/crates/rune/src/runtime/format.rs index c35943afa..a71839da2 100644 --- a/crates/rune/src/runtime/format.rs +++ b/crates/rune/src/runtime/format.rs @@ -13,7 +13,7 @@ use crate as rune; use crate::alloc::clone::TryClone; use crate::alloc::fmt::TryWrite; use crate::alloc::String; -use crate::runtime::{Formatter, Inline, ProtocolCaller, RefRepr, Value, VmErrorKind, VmResult}; +use crate::runtime::{Formatter, Inline, ProtocolCaller, ReprRef, Value, VmErrorKind, VmResult}; use crate::{Any, TypeHash}; /// Error raised when trying to parse a type string and it fails. @@ -208,8 +208,8 @@ impl FormatSpec { caller: &mut dyn ProtocolCaller, ) -> VmResult<()> { 'fallback: { - match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(value) => match value { + match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Char(c) => { vm_try!(f.buf_mut().try_push(*c)); vm_try!(self.format_fill(f, self.align, self.fill, None)); @@ -228,10 +228,10 @@ impl FormatSpec { break 'fallback; } }, - RefRepr::Mutable(..) => { + ReprRef::Mutable(..) => { break 'fallback; } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); vm_try!(f.buf_mut().try_push_str(&s)); @@ -256,8 +256,8 @@ impl FormatSpec { caller: &mut dyn ProtocolCaller, ) -> VmResult<()> { 'fallback: { - match vm_try!(value.as_ref_repr()) { - RefRepr::Inline(value) => match value { + match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Signed(n) => { let (n, align, fill, sign) = self.int_traits(*n); vm_try!(self.format_number(f.buf_mut(), n)); @@ -272,10 +272,10 @@ impl FormatSpec { break 'fallback; } }, - RefRepr::Mutable(..) => { + ReprRef::Mutable(..) => { break 'fallback; } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); vm_try!(vm_write!(f, "{s:?}")); diff --git a/crates/rune/src/runtime/from_value.rs b/crates/rune/src/runtime/from_value.rs index 50be90f75..7f4a8a5eb 100644 --- a/crates/rune/src/runtime/from_value.rs +++ b/crates/rune/src/runtime/from_value.rs @@ -247,7 +247,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - value.into_any() + value.downcast() } } @@ -257,7 +257,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - value.into_any_mut() + value.into_mut() } } @@ -267,7 +267,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - value.into_any_ref() + value.into_ref() } } @@ -291,7 +291,7 @@ where T: FromValue, { fn from_value(value: Value) -> Result { - Ok(match &*value.into_option_ref()? { + Ok(match value.downcast::>()? { Some(some) => Some(T::from_value(some.clone())?), None => None, }) @@ -333,7 +333,7 @@ impl UnsafeToRef for str { type Guard = RawAnyGuard; unsafe fn unsafe_to_ref<'a>(value: Value) -> VmResult<(&'a Self, Self::Guard)> { - let string = vm_try!(value.into_any_ref::()); + let string = vm_try!(value.into_ref::()); let (string, guard) = Ref::into_raw(string); VmResult::Ok((string.as_ref().as_str(), guard)) } @@ -343,7 +343,7 @@ impl UnsafeToMut for str { type Guard = RawAnyGuard; unsafe fn unsafe_to_mut<'a>(value: Value) -> VmResult<(&'a mut Self, Self::Guard)> { - let string = vm_try!(value.into_any_mut::()); + let string = vm_try!(value.into_mut::()); let (mut string, guard) = Mut::into_raw(string); VmResult::Ok((string.as_mut().as_mut_str(), guard)) } @@ -356,7 +356,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - Ok(match &*value.into_result_ref()? { + Ok(match value.downcast::>()? { Ok(ok) => Result::Ok(T::from_value(ok.clone())?), Err(err) => Result::Err(E::from_value(err.clone())?), }) @@ -435,7 +435,7 @@ cfg_std! { T: FromValue, { fn from_value(value: Value) -> Result { - let object = value.into_any::<$crate::runtime::Object>()?; + let object = value.downcast::<$crate::runtime::Object>()?; let mut output = <$ty>::with_capacity(object.len()); @@ -462,7 +462,7 @@ macro_rules! impl_try_map { T: FromValue, { fn from_value(value: Value) -> Result { - let object = value.into_any::<$crate::runtime::Object>()?; + let object = value.downcast::<$crate::runtime::Object>()?; let mut output = <$ty>::try_with_capacity(object.len())?; diff --git a/crates/rune/src/runtime/function.rs b/crates/rune/src/runtime/function.rs index bf7bd3ea1..ded84a248 100644 --- a/crates/rune/src/runtime/function.rs +++ b/crates/rune/src/runtime/function.rs @@ -1046,7 +1046,7 @@ struct FnTupleVariant { impl FromValue for SyncFunction { #[inline] fn from_value(value: Value) -> Result { - value.into_any::()?.into_sync() + value.downcast::()?.into_sync() } } diff --git a/crates/rune/src/runtime/inst.rs b/crates/rune/src/runtime/inst.rs index 44d4f623b..1af7bbbe7 100644 --- a/crates/rune/src/runtime/inst.rs +++ b/crates/rune/src/runtime/inst.rs @@ -65,12 +65,6 @@ pub enum TypeCheck { Object, /// Matches a vector. Vec, - /// An option type, and the specified variant index. - #[musli(packed)] - Option(usize), - /// A result type, and the specified variant index. - #[musli(packed)] - Result(usize), } impl fmt::Display for TypeCheck { @@ -80,10 +74,6 @@ impl fmt::Display for TypeCheck { Self::Tuple => write!(fmt, "Tuple"), Self::Object => write!(fmt, "Object"), Self::Vec => write!(fmt, "Vec"), - Self::Option(0) => write!(fmt, "Option::Some"), - Self::Option(..) => write!(fmt, "Option::None"), - Self::Result(0) => write!(fmt, "Result::Ok"), - Self::Result(..) => write!(fmt, "Result::Err"), } } } diff --git a/crates/rune/src/runtime/mod.rs b/crates/rune/src/runtime/mod.rs index e0fef4304..bf8c8d6a9 100644 --- a/crates/rune/src/runtime/mod.rs +++ b/crates/rune/src/runtime/mod.rs @@ -165,7 +165,7 @@ pub use self::value::{ Accessor, EmptyStruct, Inline, RawValueGuard, Rtti, Struct, TupleStruct, TypeValue, Value, ValueMutGuard, ValueRefGuard, VariantRtti, }; -pub(crate) use self::value::{BorrowRefRepr, MutRepr, Mutable, OwnedRepr, RefRepr}; +pub(crate) use self::value::{Mutable, ReprMut, ReprOwned, ReprRef}; mod variant; pub use self::variant::{Variant, VariantData}; diff --git a/crates/rune/src/runtime/range.rs b/crates/rune/src/runtime/range.rs index e2f6f59e5..c13acfe84 100644 --- a/crates/rune/src/runtime/range.rs +++ b/crates/rune/src/runtime/range.rs @@ -5,7 +5,7 @@ use core::ops; use crate as rune; use crate::alloc::clone::TryClone; use crate::runtime::{ - EnvProtocolCaller, FromValue, Inline, ProtocolCaller, RefRepr, RuntimeError, ToValue, Value, + EnvProtocolCaller, FromValue, Inline, ProtocolCaller, ReprRef, RuntimeError, ToValue, Value, VmErrorKind, VmResult, }; use crate::Any; @@ -94,19 +94,16 @@ impl Range { /// ``` #[rune::function(keep)] pub fn iter(&self) -> VmResult { - let value = match ( - &vm_try!(self.start.as_ref_repr()), - vm_try!(self.end.as_ref_repr()), - ) { - (RefRepr::Inline(Inline::Unsigned(start)), RefRepr::Inline(end)) => { + let value = match (&vm_try!(self.start.as_ref()), vm_try!(self.end.as_ref())) { + (ReprRef::Inline(Inline::Unsigned(start)), ReprRef::Inline(end)) => { let end = vm_try!(end.as_integer::()); vm_try!(rune::to_value(RangeIter::new(*start..end))) } - (RefRepr::Inline(Inline::Signed(start)), RefRepr::Inline(end)) => { + (ReprRef::Inline(Inline::Signed(start)), ReprRef::Inline(end)) => { let end = vm_try!(end.as_integer::()); vm_try!(rune::to_value(RangeIter::new(*start..end))) } - (RefRepr::Inline(Inline::Char(start)), RefRepr::Inline(Inline::Char(end))) => { + (ReprRef::Inline(Inline::Char(start)), ReprRef::Inline(Inline::Char(end))) => { vm_try!(rune::to_value(RangeIter::new(*start..*end))) } (start, end) => { @@ -319,7 +316,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - let range = value.into_any::()?; + let range = value.downcast::()?; let start = Idx::from_value(range.start)?; let end = Idx::from_value(range.end)?; Ok(ops::Range { start, end }) diff --git a/crates/rune/src/runtime/range_from.rs b/crates/rune/src/runtime/range_from.rs index a58b7c13a..26a2faa2f 100644 --- a/crates/rune/src/runtime/range_from.rs +++ b/crates/rune/src/runtime/range_from.rs @@ -5,7 +5,7 @@ use core::ops; use crate as rune; use crate::alloc::clone::TryClone; use crate::runtime::{ - EnvProtocolCaller, FromValue, Inline, ProtocolCaller, RefRepr, RuntimeError, ToValue, Value, + EnvProtocolCaller, FromValue, Inline, ProtocolCaller, ReprRef, RuntimeError, ToValue, Value, VmErrorKind, VmResult, }; use crate::Any; @@ -88,14 +88,14 @@ impl RangeFrom { /// ``` #[rune::function(keep)] pub fn iter(&self) -> VmResult { - let value = match vm_try!(self.start.as_ref_repr()) { - RefRepr::Inline(Inline::Unsigned(start)) => { + let value = match vm_try!(self.start.as_ref()) { + ReprRef::Inline(Inline::Unsigned(start)) => { vm_try!(crate::to_value(RangeFromIter::new(*start..))) } - RefRepr::Inline(Inline::Signed(start)) => { + ReprRef::Inline(Inline::Signed(start)) => { vm_try!(crate::to_value(RangeFromIter::new(*start..))) } - RefRepr::Inline(Inline::Char(start)) => { + ReprRef::Inline(Inline::Char(start)) => { vm_try!(crate::to_value(RangeFromIter::new(*start..))) } start => { @@ -291,7 +291,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - let range = value.into_any::()?; + let range = value.downcast::()?; let start = Idx::from_value(range.start)?; Ok(ops::RangeFrom { start }) } diff --git a/crates/rune/src/runtime/range_full.rs b/crates/rune/src/runtime/range_full.rs index e921299c9..0691fc4ab 100644 --- a/crates/rune/src/runtime/range_full.rs +++ b/crates/rune/src/runtime/range_full.rs @@ -135,7 +135,7 @@ impl ToValue for ops::RangeFull { impl FromValue for ops::RangeFull { #[inline] fn from_value(value: Value) -> Result { - let RangeFull = value.into_any::()?; + let RangeFull = value.downcast::()?; Ok(ops::RangeFull) } } diff --git a/crates/rune/src/runtime/range_inclusive.rs b/crates/rune/src/runtime/range_inclusive.rs index 26695a109..a551f6146 100644 --- a/crates/rune/src/runtime/range_inclusive.rs +++ b/crates/rune/src/runtime/range_inclusive.rs @@ -5,7 +5,7 @@ use core::ops; use crate as rune; use crate::alloc::clone::TryClone; use crate::runtime::{ - EnvProtocolCaller, FromValue, Inline, ProtocolCaller, RefRepr, RuntimeError, ToValue, Value, + EnvProtocolCaller, FromValue, Inline, ProtocolCaller, ReprRef, RuntimeError, ToValue, Value, VmErrorKind, VmResult, }; use crate::Any; @@ -95,19 +95,16 @@ impl RangeInclusive { /// ``` #[rune::function(keep)] pub fn iter(&self) -> VmResult { - let value = match ( - vm_try!(self.start.as_ref_repr()), - vm_try!(self.end.as_ref_repr()), - ) { - (RefRepr::Inline(Inline::Unsigned(start)), RefRepr::Inline(end)) => { + let value = match (vm_try!(self.start.as_ref()), vm_try!(self.end.as_ref())) { + (ReprRef::Inline(Inline::Unsigned(start)), ReprRef::Inline(end)) => { let end = vm_try!(end.as_integer::()); vm_try!(rune::to_value(RangeInclusiveIter::new(*start..=end))) } - (RefRepr::Inline(Inline::Signed(start)), RefRepr::Inline(end)) => { + (ReprRef::Inline(Inline::Signed(start)), ReprRef::Inline(end)) => { let end = vm_try!(end.as_integer::()); vm_try!(rune::to_value(RangeInclusiveIter::new(*start..=end))) } - (RefRepr::Inline(Inline::Char(start)), RefRepr::Inline(Inline::Char(end))) => { + (ReprRef::Inline(Inline::Char(start)), ReprRef::Inline(Inline::Char(end))) => { vm_try!(rune::to_value(RangeInclusiveIter::new(*start..=*end))) } (start, end) => { @@ -320,7 +317,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - let range = value.into_any::()?; + let range = value.downcast::()?; let start = Idx::from_value(range.start)?; let end = Idx::from_value(range.end)?; Ok(start..=end) diff --git a/crates/rune/src/runtime/range_to.rs b/crates/rune/src/runtime/range_to.rs index f4e2d2700..7746b68f7 100644 --- a/crates/rune/src/runtime/range_to.rs +++ b/crates/rune/src/runtime/range_to.rs @@ -202,7 +202,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - let range = value.into_any::()?; + let range = value.downcast::()?; let end = Idx::from_value(range.end)?; Ok(ops::RangeTo { end }) } diff --git a/crates/rune/src/runtime/range_to_inclusive.rs b/crates/rune/src/runtime/range_to_inclusive.rs index c3a05540f..23feb5ede 100644 --- a/crates/rune/src/runtime/range_to_inclusive.rs +++ b/crates/rune/src/runtime/range_to_inclusive.rs @@ -200,7 +200,7 @@ where { #[inline] fn from_value(value: Value) -> Result { - let range = value.into_any::()?; + let range = value.downcast::()?; let end = Idx::from_value(range.end)?; Ok(ops::RangeToInclusive { end }) } diff --git a/crates/rune/src/runtime/ref.rs b/crates/rune/src/runtime/ref.rs index 0297fc319..a0f4ce078 100644 --- a/crates/rune/src/runtime/ref.rs +++ b/crates/rune/src/runtime/ref.rs @@ -16,7 +16,17 @@ pub(super) struct RefVtable { type DropFn = unsafe fn(NonNull<()>); -/// A strong reference to the given type. +/// A strong owned reference to the given type that can be safely dereferenced. +/// +/// # Examples +/// +/// Constructed from a static value: +/// +/// ```rust +/// use rune::Ref; +/// +/// let value: Ref = Ref::from_static("hello world"); +/// ``` pub struct Ref { value: NonNull, guard: RawAnyGuard, @@ -30,7 +40,7 @@ impl From> for Ref { /// /// ``` /// use std::rc::Rc; - /// use rune::runtime::Ref; + /// use rune::Ref; /// /// let value: Ref = Ref::from(Rc::new(String::from("hello world"))); /// assert_eq!(value.as_ref(), "hello world"); @@ -57,7 +67,7 @@ impl From> for Ref { /// /// ``` /// use std::sync::Arc; - /// use rune::runtime::Ref; + /// use rune::Ref; /// /// let value: Ref = Ref::from(Arc::new(String::from("hello world"))); /// assert_eq!(value.as_ref(), "hello world"); @@ -81,7 +91,16 @@ impl Ref { Self { value, guard } } - /// Construct a static reference. + /// Construct an owned reference from a static value. + /// + /// # Examples + /// + /// ```rust + /// use rune::Ref; + /// + /// let value: Ref = Ref::from_static("Hello World"); + /// assert_eq!(value.as_ref(), "Hello World"); + /// ``` pub const fn from_static(value: &'static T) -> Ref { let value = unsafe { NonNull::new_unchecked((value as *const T).cast_mut()) }; let guard = RawAnyGuard::new(NonNull::dangling(), &RefVtable { drop: |_| {} }); @@ -93,7 +112,8 @@ impl Ref { /// # Examples /// /// ``` - /// use rune::runtime::{Bytes, Ref}; + /// use rune::Ref; + /// use rune::runtime::Bytes; /// use rune::alloc::try_vec; /// /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?; @@ -123,7 +143,8 @@ impl Ref { /// # Examples /// /// ``` - /// use rune::runtime::{Bytes, Ref}; + /// use rune::Ref; + /// use rune::runtime::Bytes; /// use rune::alloc::try_vec; /// /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?; @@ -206,7 +227,19 @@ where } } -/// A strong mutable reference to the given type. +/// A strong owned mutable reference to the given type that can be safely +/// dereferenced. +/// +/// # Examples +/// +/// Constructed from a static value: +/// +/// ```rust +/// use rune::Mut; +/// +/// let value: Mut<[u8]> = Mut::from_static(&mut [][..]); +/// assert_eq!(&value[..], b""); +/// ``` pub struct Mut { value: NonNull, guard: RawAnyGuard, @@ -217,7 +250,16 @@ impl Mut { Self { value, guard } } - /// Construct a static mutable reference. + /// Construct an owned mutable reference from a static value. + /// + /// # Examples + /// + /// ```rust + /// use rune::Mut; + /// + /// let value: Mut<[u8]> = Mut::from_static(&mut [][..]); + /// assert_eq!(&value[..], b""); + /// ``` pub fn from_static(value: &'static mut T) -> Mut { let value = unsafe { NonNull::new_unchecked((value as *const T).cast_mut()) }; let guard = RawAnyGuard::new(NonNull::dangling(), &RefVtable { drop: |_| {} }); @@ -229,7 +271,8 @@ impl Mut { /// # Examples /// /// ``` - /// use rune::runtime::{Bytes, Mut}; + /// use rune::Mut; + /// use rune::runtime::Bytes; /// use rune::alloc::try_vec; /// /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?; @@ -260,7 +303,8 @@ impl Mut { /// # Examples /// /// ``` - /// use rune::runtime::{Bytes, Mut}; + /// use rune::Mut; + /// use rune::runtime::Bytes; /// use rune::alloc::try_vec; /// /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?; diff --git a/crates/rune/src/runtime/tests.rs b/crates/rune/src/runtime/tests.rs index e1723d7a1..0c8a2a823 100644 --- a/crates/rune/src/runtime/tests.rs +++ b/crates/rune/src/runtime/tests.rs @@ -44,8 +44,8 @@ fn test_clone_take() -> Result<()> { let v = Value::from(AnyObj::new(Thing(0))?); let v2 = v.clone(); let v3 = v.clone(); - assert_eq!(Thing(0), v2.into_any::()?); - assert!(v3.into_any::().is_err()); + assert_eq!(Thing(0), v2.downcast::()?); + assert!(v3.downcast::().is_err()); let any = v.into_any_obj()?; assert_eq!(any.type_hash(), Thing::HASH); Ok(()) @@ -549,7 +549,7 @@ fn test_clone_issue() { let shared = Value::try_from(Bytes::new()).unwrap(); let _ = { - let shared = shared.into_any_ref::().unwrap(); + let shared = shared.into_ref::().unwrap(); let out = shared.try_clone().unwrap(); out }; diff --git a/crates/rune/src/runtime/value.rs b/crates/rune/src/runtime/value.rs index 88ba2d463..8b9cf78d6 100644 --- a/crates/rune/src/runtime/value.rs +++ b/crates/rune/src/runtime/value.rs @@ -77,64 +77,47 @@ enum Repr { Any(AnyObj), } -pub(crate) enum OwnedRepr { +pub(crate) enum ReprOwned { Inline(Inline), Mutable(Mutable), Any(AnyObj), } -impl OwnedRepr { +impl ReprOwned { #[inline] pub(crate) fn type_info(&self) -> TypeInfo { match self { - OwnedRepr::Inline(value) => value.type_info(), - OwnedRepr::Mutable(value) => value.type_info(), - OwnedRepr::Any(value) => value.type_info(), + ReprOwned::Inline(value) => value.type_info(), + ReprOwned::Mutable(value) => value.type_info(), + ReprOwned::Any(value) => value.type_info(), } } } -pub(crate) enum RefRepr<'a> { +pub(crate) enum ReprRef<'a> { Inline(&'a Inline), Mutable(&'a Shared), Any(&'a AnyObj), } -impl RefRepr<'_> { +impl ReprRef<'_> { #[inline] pub(crate) fn type_info(&self) -> Result { match self { - RefRepr::Inline(value) => Ok(value.type_info()), - RefRepr::Mutable(value) => Ok(value.borrow_ref()?.type_info()), - RefRepr::Any(value) => Ok(value.type_info()), + ReprRef::Inline(value) => Ok(value.type_info()), + ReprRef::Mutable(value) => Ok(value.borrow_ref()?.type_info()), + ReprRef::Any(value) => Ok(value.type_info()), } } } /// Access the internals of a value mutably. -pub(crate) enum MutRepr<'a> { +pub(crate) enum ReprMut<'a> { Inline(&'a mut Inline), Mutable(#[allow(unused)] &'a mut Shared), Any(#[allow(unused)] &'a mut AnyObj), } -pub(crate) enum BorrowRefRepr<'a> { - Inline(&'a Inline), - Mutable(BorrowRef<'a, Mutable>), - Any(&'a AnyObj), -} - -impl<'a> BorrowRefRepr<'a> { - #[inline] - pub(crate) fn type_info(&self) -> TypeInfo { - match self { - BorrowRefRepr::Inline(value) => value.type_info(), - BorrowRefRepr::Mutable(value) => value.type_info(), - BorrowRefRepr::Any(value) => value.type_info(), - } - } -} - /// An entry on the stack. pub struct Value { repr: Repr, @@ -354,8 +337,8 @@ impl Value { caller: &mut dyn ProtocolCaller, ) -> VmResult<()> { 'fallback: { - match vm_try!(self.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => match value { + match vm_try!(self.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Char(c) => { vm_try!(f.try_write_char(*c)); } @@ -414,21 +397,19 @@ impl Value { pub(crate) fn clone_with(&self, caller: &mut dyn ProtocolCaller) -> VmResult { 'fallback: { - let value = match vm_try!(self.as_ref_repr()) { - RefRepr::Inline(value) => { + let value = match vm_try!(self.as_ref()) { + ReprRef::Inline(value) => { return VmResult::Ok(Self { repr: Repr::Inline(*value), }); } - RefRepr::Mutable(value) => match &*vm_try!(value.borrow_ref()) { - Mutable::Option(value) => Mutable::Option(vm_try!(value.try_clone())), - Mutable::Result(value) => Mutable::Result(vm_try!(value.try_clone())), + ReprRef::Mutable(value) => match &*vm_try!(value.borrow_ref()) { 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())), }, - RefRepr::Any(..) => { + ReprRef::Any(..) => { break 'fallback; } }; @@ -482,12 +463,6 @@ impl Value { }; match &*vm_try!(value.borrow_ref()) { - Mutable::Option(value) => { - vm_try!(vm_write!(f, "{value:?}")); - } - Mutable::Result(value) => { - vm_try!(vm_write!(f, "{value:?}")); - } Mutable::EmptyStruct(value) => { vm_try!(vm_write!(f, "{value:?}")); } @@ -681,7 +656,7 @@ impl Value { #[inline] pub fn into_string(self) -> Result { match self.take_repr()? { - OwnedRepr::Any(value) => Ok(value.downcast()?), + ReprOwned::Any(value) => Ok(value.downcast()?), actual => Err(RuntimeError::expected::(actual.type_info())), } } @@ -691,18 +666,17 @@ impl Value { #[inline] pub fn into_type_value(self) -> Result { match self.take_repr()? { - OwnedRepr::Inline(value) => match value { + ReprOwned::Inline(value) => match value { Inline::Unit => Ok(TypeValue::Unit), value => Ok(TypeValue::NotTypedInline(NotTypedInlineValue(value))), }, - OwnedRepr::Mutable(value) => match value { + ReprOwned::Mutable(value) => match 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)), - value => Ok(TypeValue::NotTypedMutable(NotTypedMutableValue(value))), }, - OwnedRepr::Any(value) => match value.type_hash() { + ReprOwned::Any(value) => match value.type_hash() { OwnedTuple::HASH => Ok(TypeValue::Tuple(value.downcast()?)), Object::HASH => Ok(TypeValue::Object(value.downcast()?)), _ => Ok(TypeValue::NotTypedAnyObj(NotTypedAnyObj(value))), @@ -713,9 +687,9 @@ impl Value { /// Coerce into a unit. #[inline] pub fn into_unit(&self) -> Result<(), RuntimeError> { - match self.borrow_ref_repr()? { - BorrowRefRepr::Inline(Inline::Unit) => Ok(()), - value => Err(RuntimeError::expected::<()>(value.type_info())), + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(()), + value => Err(RuntimeError::expected::<()>(value.type_info()?)), } } @@ -768,26 +742,6 @@ impl Value { as_type_mut, } - clone_into! { - /// Coerce into [`Option`]. - Option(Option), - into_option_ref, - into_option_mut, - borrow_option_ref, - borrow_option_mut, - as_option, - } - - clone_into! { - /// Coerce into [`Result`]. - Result(Result), - into_result_ref, - into_result_mut, - borrow_result_ref, - borrow_result_mut, - as_result, - } - into! { /// Coerce into [`Struct`] Struct(Struct), @@ -804,13 +758,13 @@ impl Value { /// and does not consume it. #[inline] pub fn borrow_tuple_ref(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(Inline::Unit) => Ok(BorrowRef::from_static(Tuple::new(&[]))), - RefRepr::Inline(value) => Err(RuntimeError::expected::(value.type_info())), - RefRepr::Mutable(value) => Err(RuntimeError::expected::( + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(BorrowRef::from_static(Tuple::new(&[]))), + ReprRef::Inline(value) => Err(RuntimeError::expected::(value.type_info())), + ReprRef::Mutable(value) => Err(RuntimeError::expected::( value.borrow_ref()?.type_info(), )), - RefRepr::Any(value) => { + ReprRef::Any(value) => { let value = value.borrow_ref::()?; let value = BorrowRef::map(value, OwnedTuple::as_ref); Ok(value) @@ -824,13 +778,13 @@ impl Value { /// does not consume it. #[inline] pub fn borrow_tuple_mut(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(Inline::Unit) => Ok(BorrowMut::from_static(Tuple::new_mut(&mut []))), - RefRepr::Inline(value) => Err(RuntimeError::expected::(value.type_info())), - RefRepr::Mutable(value) => Err(RuntimeError::expected::( + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(BorrowMut::from_static(Tuple::new_mut(&mut []))), + ReprRef::Inline(value) => Err(RuntimeError::expected::(value.type_info())), + ReprRef::Mutable(value) => Err(RuntimeError::expected::( value.borrow_ref()?.type_info(), )), - RefRepr::Any(value) => { + ReprRef::Any(value) => { let value = value.borrow_mut::()?; let value = BorrowMut::map(value, OwnedTuple::as_mut); Ok(value) @@ -844,13 +798,13 @@ impl Value { /// does not consume it. #[inline] pub fn into_tuple(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(Inline::Unit) => Ok(Tuple::from_boxed(Box::default())), - RefRepr::Inline(value) => Err(RuntimeError::expected::(value.type_info())), - RefRepr::Mutable(value) => Err(RuntimeError::expected::( + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(Tuple::from_boxed(Box::default())), + ReprRef::Inline(value) => Err(RuntimeError::expected::(value.type_info())), + ReprRef::Mutable(value) => Err(RuntimeError::expected::( value.borrow_ref()?.type_info(), )), - RefRepr::Any(value) => Ok(value.clone().downcast::()?.into_boxed_tuple()), + ReprRef::Any(value) => Ok(value.clone().downcast::()?.into_boxed_tuple()), } } @@ -860,13 +814,13 @@ impl Value { /// does not consume it. #[inline] pub fn into_tuple_ref(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(Inline::Unit) => Ok(Ref::from_static(Tuple::new(&[]))), - RefRepr::Inline(value) => Err(RuntimeError::expected::(value.type_info())), - RefRepr::Mutable(value) => Err(RuntimeError::expected::( + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(Ref::from_static(Tuple::new(&[]))), + ReprRef::Inline(value) => Err(RuntimeError::expected::(value.type_info())), + ReprRef::Mutable(value) => Err(RuntimeError::expected::( value.borrow_ref()?.type_info(), )), - RefRepr::Any(value) => { + ReprRef::Any(value) => { let value = value.clone().into_ref::()?; let value = Ref::map(value, OwnedTuple::as_ref); Ok(value) @@ -880,13 +834,13 @@ impl Value { /// does not consume it. #[inline] pub fn into_tuple_mut(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(Inline::Unit) => Ok(Mut::from_static(Tuple::new_mut(&mut []))), - RefRepr::Inline(value) => Err(RuntimeError::expected::(value.type_info())), - RefRepr::Mutable(value) => Err(RuntimeError::expected::( + match self.as_ref()? { + ReprRef::Inline(Inline::Unit) => Ok(Mut::from_static(Tuple::new_mut(&mut []))), + ReprRef::Inline(value) => Err(RuntimeError::expected::(value.type_info())), + ReprRef::Mutable(value) => Err(RuntimeError::expected::( value.borrow_ref()?.type_info(), )), - RefRepr::Any(value) => { + ReprRef::Any(value) => { let value = value.clone().into_mut::()?; let value = Mut::map(value, OwnedTuple::as_mut); Ok(value) @@ -945,8 +899,13 @@ impl Value { } /// Try to coerce value into a typed reference. + /// + /// # Safety + /// + /// The returned pointer is only valid to dereference as long as the + /// returned guard is live. #[inline] - pub fn into_any_ref(self) -> Result, RuntimeError> + pub fn into_any_ref_ptr(self) -> Result<(NonNull, RawValueGuard), RuntimeError> where T: Any, { @@ -956,18 +915,23 @@ impl Value { Repr::Mutable(value) => Err(RuntimeError::expected_any::( value.borrow_ref()?.type_info(), )), - Repr::Any(value) => Ok(value.into_ref()?), + Repr::Any(value) => { + let (ptr, guard) = value.borrow_ref_ptr::()?; + let guard = RawValueGuard { guard }; + Ok((ptr, guard)) + } } } - /// Try to coerce value into a typed reference. + /// Try to coerce value into a typed mutable reference. /// /// # Safety /// /// The returned pointer is only valid to dereference as long as the /// returned guard is live. #[inline] - pub fn into_any_ref_ptr(self) -> Result<(NonNull, RawValueGuard), RuntimeError> + #[doc(hidden)] + pub fn into_any_mut_ptr(self) -> Result<(NonNull, RawValueGuard), RuntimeError> where T: Any, { @@ -978,16 +942,44 @@ impl Value { value.borrow_ref()?.type_info(), )), Repr::Any(value) => { - let (ptr, guard) = value.borrow_ref_ptr::()?; + let (ptr, guard) = value.borrow_mut_ptr::()?; let guard = RawValueGuard { guard }; Ok((ptr, guard)) } } } - /// Try to coerce value into a typed mutable reference. + /// Downcast the value into a stored value that implements `Any`. + /// + /// This takes the interior value, making it inaccessible to other owned + /// references. + /// + /// You should usually prefer to use [`rune::from_value`] instead of this + /// directly. + /// + /// [`rune::from_value`]: crate::from_value + /// + /// # Examples + /// + /// ```rust + /// use rune::Value; + /// use rune::alloc::String; + /// + /// let a = Value::try_from("Hello World")?; + /// let b = a.clone(); + /// + /// assert!(b.borrow_ref::().is_ok()); + /// + /// // NB: The interior representation of the stored string is from rune-alloc. + /// let a = a.downcast::()?; + /// + /// assert!(b.borrow_ref::().is_err()); + /// + /// assert_eq!(a, "Hello World"); + /// # Ok::<_, rune::support::Error>(()) + /// ``` #[inline] - pub fn into_any_mut(self) -> Result, RuntimeError> + pub fn downcast(self) -> Result where T: Any, { @@ -997,52 +989,82 @@ impl Value { Repr::Mutable(value) => Err(RuntimeError::expected_any::( value.borrow_ref()?.type_info(), )), - Repr::Any(value) => Ok(value.into_mut()?), + Repr::Any(value) => Ok(value.downcast::()?), } } - /// Try to coerce value into a typed mutable reference. + /// Borrow the value as a typed reference of type `T`. /// - /// # Safety + /// # Examples /// - /// The returned pointer is only valid to dereference as long as the - /// returned guard is live. + /// ```rust + /// use rune::Value; + /// use rune::alloc::String; + /// + /// let a = Value::try_from("Hello World")?; + /// let b = a.clone(); + /// + /// assert!(b.borrow_ref::().is_ok()); + /// + /// // NB: The interior representation of the stored string is from rune-alloc. + /// let a = a.downcast::()?; + /// + /// assert!(b.borrow_ref::().is_err()); + /// + /// assert_eq!(a, "Hello World"); + /// # Ok::<_, rune::support::Error>(()) + /// ``` #[inline] - pub fn into_any_mut_ptr(self) -> Result<(NonNull, RawValueGuard), RuntimeError> + pub fn borrow_ref(&self) -> Result, RuntimeError> where T: Any, { - match self.repr { + match &self.repr { Repr::Empty => Err(RuntimeError::from(AccessError::empty())), Repr::Inline(value) => Err(RuntimeError::expected_any::(value.type_info())), Repr::Mutable(value) => Err(RuntimeError::expected_any::( value.borrow_ref()?.type_info(), )), - Repr::Any(value) => { - let (ptr, guard) = value.borrow_mut_ptr::()?; - let guard = RawValueGuard { guard }; - Ok((ptr, guard)) - } + Repr::Any(value) => Ok(value.borrow_ref()?), } } - /// Borrow the value as a typed reference. + /// Try to coerce value into a typed reference of type `T`. + /// + /// You should usually prefer to use [`rune::from_value`] instead of this + /// directly. + /// + /// [`rune::from_value`]: crate::from_value + /// + /// # Examples + /// + /// ```rust + /// use rune::Value; + /// use rune::alloc::String; + /// + /// let mut a = Value::try_from("Hello World")?; + /// let b = a.clone(); + /// + /// assert_eq!(a.into_ref::()?.as_str(), "Hello World"); + /// assert_eq!(b.into_ref::()?.as_str(), "Hello World"); + /// # Ok::<_, rune::support::Error>(()) + /// ``` #[inline] - pub fn borrow_ref(&self) -> Result, RuntimeError> + pub fn into_ref(self) -> Result, RuntimeError> where T: Any, { - match &self.repr { + match self.repr { Repr::Empty => Err(RuntimeError::from(AccessError::empty())), Repr::Inline(value) => Err(RuntimeError::expected_any::(value.type_info())), Repr::Mutable(value) => Err(RuntimeError::expected_any::( value.borrow_ref()?.type_info(), )), - Repr::Any(value) => Ok(value.borrow_ref()?), + Repr::Any(value) => Ok(value.into_ref()?), } } - /// Borrow the value as a mutable typed reference. + /// Try to borrow value into a typed mutable reference of type `T`. #[inline] pub fn borrow_mut(&self) -> Result, RuntimeError> where @@ -1058,9 +1080,36 @@ impl Value { } } - /// Try to coerce value into a typed value. + /// Try to coerce value into a typed mutable reference of type `T`. + /// + /// You should usually prefer to use [`rune::from_value`] instead of this + /// directly since it supports transparently coercing into types like + /// [`Mut`]. + /// + /// [`rune::from_value`]: crate::from_value + /// + /// # Examples + /// + /// ```rust + /// use rune::{Mut, Value}; + /// use rune::alloc::String; + /// + /// let mut a = Value::try_from("Hello World")?; + /// let b = a.clone(); + /// + /// fn modify_string(mut s: Mut) { + /// assert_eq!(s.as_str(), "Hello World"); + /// s.make_ascii_lowercase(); + /// assert_eq!(s.as_str(), "hello world"); + /// } + /// + /// modify_string(a.into_mut::()?); + /// + /// assert_eq!(b.borrow_mut::()?.as_str(), "hello world"); + /// # Ok::<_, rune::support::Error>(()) + /// ``` #[inline] - pub fn into_any(self) -> Result + pub fn into_mut(self) -> Result, RuntimeError> where T: Any, { @@ -1070,7 +1119,7 @@ impl Value { Repr::Mutable(value) => Err(RuntimeError::expected_any::( value.borrow_ref()?.type_info(), )), - Repr::Any(value) => Ok(value.downcast::()?), + Repr::Any(value) => Ok(value.into_mut()?), } } @@ -1120,19 +1169,20 @@ impl Value { b: &Value, caller: &mut dyn ProtocolCaller, ) -> VmResult { - match (vm_try!(self.as_ref_repr()), vm_try!(b.borrow_ref_repr())) { - (RefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { + match (vm_try!(self.as_ref()), vm_try!(b.as_ref())) { + (ReprRef::Inline(a), ReprRef::Inline(b)) => { return VmResult::Ok(vm_try!(a.partial_eq(b))); } - (RefRepr::Inline(a), b) => { + (ReprRef::Inline(a), b) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: Protocol::PARTIAL_EQ.name, lhs: a.type_info(), - rhs: b.type_info(), + rhs: vm_try!(b.type_info()), }); } - (RefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => { + (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { let a = vm_try!(a.borrow_ref()); + let b = vm_try!(b.borrow_ref()); match (&*a, &*b) { (Mutable::EmptyStruct(a), Mutable::EmptyStruct(b)) => { @@ -1160,20 +1210,10 @@ impl Value { return Variant::partial_eq_with(a, b, caller); } } - (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), - }, _ => {} } } - (RefRepr::Any(value), _) => match value.type_hash() { + (ReprRef::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); @@ -1215,8 +1255,8 @@ impl Value { hasher: &mut Hasher, caller: &mut dyn ProtocolCaller, ) -> VmResult<()> { - match vm_try!(self.as_ref_repr()) { - RefRepr::Inline(value) => match value { + match vm_try!(self.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Unsigned(value) => { hasher.write_u64(*value); return VmResult::Ok(()); @@ -1244,7 +1284,7 @@ impl Value { }); } }, - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { Vec::HASH => { let vec = vm_try!(value.borrow_ref::()); return Vec::hash_with(&vec, hasher, caller); @@ -1291,58 +1331,50 @@ impl Value { /// This is the basis for the eq operation (`==`). #[cfg_attr(feature = "bench", inline(never))] pub(crate) fn eq_with(&self, b: &Value, caller: &mut dyn ProtocolCaller) -> VmResult { - match ( - vm_try!(self.borrow_ref_repr()), - vm_try!(b.borrow_ref_repr()), - ) { - (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { + match (vm_try!(self.as_ref()), vm_try!(b.as_ref())) { + (ReprRef::Inline(a), ReprRef::Inline(b)) => { return a.eq(b); } - (BorrowRefRepr::Inline(lhs), rhs) => { + (ReprRef::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: Protocol::EQ.name, lhs: lhs.type_info(), - rhs: rhs.type_info(), + rhs: vm_try!(rhs.type_info()), }); } - (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => 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); + (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { + let a = vm_try!(a.borrow_ref()); + let b = vm_try!(b.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); + } } - } - (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::eq_with(&a.data, &b.data, Value::eq_with, caller); + (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { + if a.rtti.hash == b.rtti.hash { + 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 { - 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 { + return Vec::eq_with(&a.data, &b.data, Value::eq_with, caller); + } } - } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().enum_hash == b.rtti().enum_hash { - return Variant::eq_with(a, b, caller); + (Mutable::Variant(a), Mutable::Variant(b)) => { + if a.rtti().enum_hash == b.rtti().enum_hash { + return Variant::eq_with(a, b, caller); + } } + _ => {} } - (Mutable::Option(a), Mutable::Option(b)) => match (a, b) { - (Some(a), Some(b)) => return Value::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::eq_with(a, b, caller), - (Err(a), Err(b)) => return Value::eq_with(a, b, caller), - _ => return VmResult::Ok(false), - }, - _ => {} - }, + } _ => {} } @@ -1384,60 +1416,50 @@ impl Value { b: &Value, caller: &mut dyn ProtocolCaller, ) -> VmResult> { - match ( - vm_try!(self.borrow_ref_repr()), - vm_try!(b.borrow_ref_repr()), - ) { - (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => { + match (vm_try!(self.as_ref()), vm_try!(b.as_ref())) { + (ReprRef::Inline(a), ReprRef::Inline(b)) => { return VmResult::Ok(vm_try!(a.partial_cmp(b))) } - (BorrowRefRepr::Inline(lhs), rhs) => { + (ReprRef::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: Protocol::PARTIAL_CMP.name, lhs: lhs.type_info(), - rhs: rhs.type_info(), + rhs: vm_try!(rhs.type_info()), }) } - (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => 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(Some(Ordering::Equal)); + (ReprRef::Mutable(a), ReprRef::Mutable(b)) => { + let a = vm_try!(a.borrow_ref()); + let b = vm_try!(b.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(Some(Ordering::Equal)); + } } - } - (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::partial_cmp_with(&a.data, &b.data, caller); + (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Vec::partial_cmp_with(&a.data, &b.data, caller); + } } - } - (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::partial_cmp_with(&a.data, &b.data, caller); + (Mutable::Struct(a), Mutable::Struct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Vec::partial_cmp_with(&a.data, &b.data, caller); + } } - } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().enum_hash == b.rtti().enum_hash { - return Variant::partial_cmp_with(a, b, caller); + (Mutable::Variant(a), Mutable::Variant(b)) => { + if a.rtti().enum_hash == b.rtti().enum_hash { + return Variant::partial_cmp_with(a, b, caller); + } } + _ => {} } - (Mutable::Option(a), Mutable::Option(b)) => match (a, b) { - (Some(a), Some(b)) => return Value::partial_cmp_with(a, b, caller), - (None, None) => return VmResult::Ok(Some(Ordering::Equal)), - (Some(..), None) => return VmResult::Ok(Some(Ordering::Greater)), - (None, Some(..)) => return VmResult::Ok(Some(Ordering::Less)), - }, - (Mutable::Result(a), Mutable::Result(b)) => match (a, b) { - (Ok(a), Ok(b)) => return Value::partial_cmp_with(a, b, caller), - (Err(a), Err(b)) => return Value::partial_cmp_with(a, b, caller), - (Ok(..), Err(..)) => return VmResult::Ok(Some(Ordering::Greater)), - (Err(..), Ok(..)) => return VmResult::Ok(Some(Ordering::Less)), - }, - _ => {} - }, + } _ => {} } @@ -1479,56 +1501,46 @@ impl Value { b: &Value, caller: &mut dyn ProtocolCaller, ) -> VmResult { - match ( - vm_try!(self.borrow_ref_repr()), - vm_try!(b.borrow_ref_repr()), - ) { - (BorrowRefRepr::Inline(a), BorrowRefRepr::Inline(b)) => return a.cmp(b), - (BorrowRefRepr::Mutable(a), BorrowRefRepr::Mutable(b)) => 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(Ordering::Equal); + 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()); + + 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(Ordering::Equal); + } } - } - (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::cmp_with(&a.data, &b.data, caller); + (Mutable::TupleStruct(a), Mutable::TupleStruct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Vec::cmp_with(&a.data, &b.data, caller); + } } - } - (Mutable::Struct(a), Mutable::Struct(b)) => { - if a.rtti.hash == b.rtti.hash { - return Vec::cmp_with(&a.data, &b.data, caller); + (Mutable::Struct(a), Mutable::Struct(b)) => { + if a.rtti.hash == b.rtti.hash { + return Vec::cmp_with(&a.data, &b.data, caller); + } } - } - (Mutable::Variant(a), Mutable::Variant(b)) => { - if a.rtti().enum_hash == b.rtti().enum_hash { - return Variant::cmp_with(a, b, caller); + (Mutable::Variant(a), Mutable::Variant(b)) => { + if a.rtti().enum_hash == b.rtti().enum_hash { + return Variant::cmp_with(a, b, caller); + } } + _ => {} } - (Mutable::Option(a), Mutable::Option(b)) => match (a, b) { - (Some(a), Some(b)) => return Value::cmp_with(a, b, caller), - (None, None) => return VmResult::Ok(Ordering::Equal), - (Some(..), None) => return VmResult::Ok(Ordering::Greater), - (None, Some(..)) => return VmResult::Ok(Ordering::Less), - }, - (Mutable::Result(a), Mutable::Result(b)) => match (a, b) { - (Ok(a), Ok(b)) => return Value::cmp_with(a, b, caller), - (Err(a), Err(b)) => return Value::cmp_with(a, b, caller), - (Ok(..), Err(..)) => return VmResult::Ok(Ordering::Greater), - (Err(..), Ok(..)) => return VmResult::Ok(Ordering::Less), - }, - _ => {} - }, - (BorrowRefRepr::Inline(lhs), rhs) => { + } + (ReprRef::Inline(lhs), rhs) => { return VmResult::err(VmErrorKind::UnsupportedBinaryOperation { op: Protocol::CMP.name, lhs: lhs.type_info(), - rhs: rhs.type_info(), + rhs: vm_try!(rhs.type_info()), }); } _ => {} @@ -1622,39 +1634,30 @@ impl Value { } } - pub(crate) fn take_repr(self) -> Result { + pub(crate) fn take_repr(self) -> Result { match self.repr { Repr::Empty => Err(AccessError::empty()), - Repr::Inline(value) => Ok(OwnedRepr::Inline(value)), - Repr::Mutable(value) => Ok(OwnedRepr::Mutable(value.take()?)), - Repr::Any(value) => Ok(OwnedRepr::Any(value)), + Repr::Inline(value) => Ok(ReprOwned::Inline(value)), + Repr::Mutable(value) => Ok(ReprOwned::Mutable(value.take()?)), + Repr::Any(value) => Ok(ReprOwned::Any(value)), } } - pub(crate) fn borrow_ref_repr(&self) -> Result, AccessError> { + pub(crate) fn as_ref(&self) -> Result, AccessError> { match &self.repr { + Repr::Inline(value) => Ok(ReprRef::Inline(value)), + Repr::Mutable(value) => Ok(ReprRef::Mutable(value)), + Repr::Any(value) => Ok(ReprRef::Any(value)), Repr::Empty => Err(AccessError::empty()), - Repr::Inline(value) => Ok(BorrowRefRepr::Inline(value)), - Repr::Mutable(value) => Ok(BorrowRefRepr::Mutable(value.borrow_ref()?)), - Repr::Any(value) => Ok(BorrowRefRepr::Any(value)), } } - pub(crate) fn as_ref_repr(&self) -> Result, AccessError> { - match &self.repr { - Repr::Inline(value) => Ok(RefRepr::Inline(value)), - Repr::Mutable(value) => Ok(RefRepr::Mutable(value)), - Repr::Any(value) => Ok(RefRepr::Any(value)), - Repr::Empty => Err(AccessError::empty()), - } - } - - pub(crate) fn as_mut_repr(&mut self) -> Result, AccessError> { + pub(crate) fn as_mut(&mut self) -> Result, AccessError> { match &mut self.repr { Repr::Empty => Err(AccessError::empty()), - Repr::Inline(value) => Ok(MutRepr::Inline(value)), - Repr::Mutable(value) => Ok(MutRepr::Mutable(value)), - Repr::Any(value) => Ok(MutRepr::Any(value)), + Repr::Inline(value) => Ok(ReprMut::Inline(value)), + Repr::Mutable(value) => Ok(ReprMut::Mutable(value)), + Repr::Any(value) => Ok(ReprMut::Any(value)), } } @@ -1888,11 +1891,8 @@ any_from! { super::Function, super::Future, super::Object, -} - -from_container! { - Option => Option, - Result => Result, + Option, + Result, } signed_value_from!(i8, i16, i32); @@ -1954,10 +1954,6 @@ impl TryClone for Value { #[doc(hidden)] pub struct NotTypedInlineValue(Inline); -/// Wrapper for a value kind. -#[doc(hidden)] -pub struct NotTypedMutableValue(Mutable); - /// Wrapper for an any ref value kind. #[doc(hidden)] pub struct NotTypedAnyObj(AnyObj); @@ -1985,9 +1981,6 @@ pub enum TypeValue { NotTypedInline(NotTypedInlineValue), /// Not a typed value. #[doc(hidden)] - NotTypedMutable(NotTypedMutableValue), - /// Not a typed value. - #[doc(hidden)] NotTypedAnyObj(NotTypedAnyObj), } @@ -2004,17 +1997,12 @@ impl TypeValue { TypeValue::Struct(object) => object.type_info(), TypeValue::Variant(empty) => empty.type_info(), TypeValue::NotTypedInline(value) => value.0.type_info(), - TypeValue::NotTypedMutable(value) => value.0.type_info(), TypeValue::NotTypedAnyObj(value) => value.0.type_info(), } } } pub(crate) enum Mutable { - /// An empty value indicating nothing. - Option(Option), - /// A stored result in a slot. - Result(Result), /// An struct with a well-defined type. EmptyStruct(EmptyStruct), /// A tuple with a well-defined type. @@ -2028,8 +2016,6 @@ pub(crate) enum Mutable { impl Mutable { pub(crate) fn type_info(&self) -> TypeInfo { match self { - Mutable::Result(..) => TypeInfo::any::>(), - Mutable::Option(..) => TypeInfo::any::>(), Mutable::EmptyStruct(empty) => empty.type_info(), Mutable::TupleStruct(tuple) => tuple.type_info(), Mutable::Struct(object) => object.type_info(), @@ -2043,8 +2029,6 @@ impl Mutable { /// *enum*, and not the type hash of the variant itself. pub(crate) fn type_hash(&self) -> Hash { match self { - Mutable::Result(..) => Result::::HASH, - Mutable::Option(..) => Option::::HASH, Mutable::EmptyStruct(empty) => empty.rtti.hash, Mutable::TupleStruct(tuple) => tuple.rtti.hash, Mutable::Struct(object) => object.rtti.hash, diff --git a/crates/rune/src/runtime/value/data.rs b/crates/rune/src/runtime/value/data.rs index 8eefcce1f..474e3d753 100644 --- a/crates/rune/src/runtime/value/data.rs +++ b/crates/rune/src/runtime/value/data.rs @@ -9,7 +9,7 @@ use crate as rune; use crate::alloc::prelude::*; use crate::runtime::{OwnedTuple, TypeInfo}; -use super::{FromValue, Mutable, OwnedRepr, Rtti, RuntimeError, Value}; +use super::{FromValue, Mutable, ReprOwned, Rtti, RuntimeError, Value}; /// A empty with a well-defined type. #[derive(TryClone)] @@ -34,10 +34,10 @@ impl EmptyStruct { impl FromValue for EmptyStruct { fn from_value(value: Value) -> Result { match value.take_repr()? { - OwnedRepr::Inline(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), - OwnedRepr::Mutable(Mutable::EmptyStruct(value)) => Ok(value), - OwnedRepr::Mutable(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), - OwnedRepr::Any(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), + ReprOwned::Inline(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), + ReprOwned::Mutable(Mutable::EmptyStruct(value)) => Ok(value), + ReprOwned::Mutable(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), + ReprOwned::Any(value) => Err(RuntimeError::expected_unit_struct(value.type_info())), } } } @@ -92,12 +92,12 @@ impl TupleStruct { impl FromValue for TupleStruct { fn from_value(value: Value) -> Result { match value.take_repr()? { - OwnedRepr::Inline(value) => Err(RuntimeError::expected_tuple_struct(value.type_info())), - OwnedRepr::Mutable(Mutable::TupleStruct(value)) => Ok(value), - OwnedRepr::Mutable(value) => { + ReprOwned::Inline(value) => Err(RuntimeError::expected_tuple_struct(value.type_info())), + ReprOwned::Mutable(Mutable::TupleStruct(value)) => Ok(value), + ReprOwned::Mutable(value) => { Err(RuntimeError::expected_tuple_struct(value.type_info())) } - OwnedRepr::Any(value) => Err(RuntimeError::expected_tuple_struct(value.type_info())), + ReprOwned::Any(value) => Err(RuntimeError::expected_tuple_struct(value.type_info())), } } } @@ -160,10 +160,10 @@ impl Struct { impl FromValue for Struct { fn from_value(value: Value) -> Result { match value.take_repr()? { - OwnedRepr::Inline(value) => Err(RuntimeError::expected_struct(value.type_info())), - OwnedRepr::Mutable(Mutable::Struct(value)) => Ok(value), - OwnedRepr::Mutable(value) => Err(RuntimeError::expected_struct(value.type_info())), - OwnedRepr::Any(value) => Err(RuntimeError::expected_struct(value.type_info())), + ReprOwned::Inline(value) => Err(RuntimeError::expected_struct(value.type_info())), + ReprOwned::Mutable(Mutable::Struct(value)) => Ok(value), + ReprOwned::Mutable(value) => Err(RuntimeError::expected_struct(value.type_info())), + ReprOwned::Any(value) => Err(RuntimeError::expected_struct(value.type_info())), } } } diff --git a/crates/rune/src/runtime/value/macros.rs b/crates/rune/src/runtime/value/macros.rs index 51f74870b..00c848c69 100644 --- a/crates/rune/src/runtime/value/macros.rs +++ b/crates/rune/src/runtime/value/macros.rs @@ -80,11 +80,11 @@ macro_rules! into_base { /// and does not consume it. #[inline] pub fn $borrow_ref(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(value) => { + match self.as_ref()? { + ReprRef::Inline(value) => { Err(RuntimeError::expected::<$ty>(value.type_info())) }, - RefRepr::Mutable(value) => { + ReprRef::Mutable(value) => { let result = BorrowRef::try_map(value.borrow_ref()?, |kind| match kind { Mutable::$kind(value) => Some(value), _ => None, @@ -95,7 +95,7 @@ macro_rules! into_base { Err(value) => Err(RuntimeError::expected::<$ty>(value.type_info())), } }, - RefRepr::Any(value) => { + ReprRef::Any(value) => { Err(RuntimeError::expected::<$ty>(value.type_info())) }, } @@ -107,11 +107,11 @@ macro_rules! into_base { /// and does not consume it. #[inline] pub fn $borrow_mut(&self) -> Result, RuntimeError> { - match self.as_ref_repr()? { - RefRepr::Inline(value) => { + match self.as_ref()? { + ReprRef::Inline(value) => { Err(RuntimeError::expected::<$ty>(value.type_info())) } - RefRepr::Mutable(value) => { + ReprRef::Mutable(value) => { let result = BorrowMut::try_map(value.borrow_mut()?, |kind| match kind { Mutable::$kind(value) => Some(value), _ => None, @@ -122,7 +122,7 @@ macro_rules! into_base { Err(value) => Err(RuntimeError::expected::<$ty>(value.type_info())), } }, - RefRepr::Any(value) => { + ReprRef::Any(value) => { Err(RuntimeError::expected::<$ty>(value.type_info())) } } @@ -155,7 +155,7 @@ macro_rules! into { #[inline] pub fn $into(self) -> Result<$ty, RuntimeError> { match self.take_repr()? { - OwnedRepr::Mutable(Mutable::$kind(value)) => Ok(value), + ReprOwned::Mutable(Mutable::$kind(value)) => Ok(value), value => Err(RuntimeError::expected::<$ty>(value.type_info())), } } @@ -219,47 +219,6 @@ macro_rules! inline_into { } } -macro_rules! clone_into { - ( - $(#[$($meta:meta)*])* - $kind:ident($ty:ty), - $into_ref:ident, - $into_mut:ident, - $borrow_ref:ident, - $borrow_mut:ident, - $as:ident, - ) => { - into_base! { - $(#[$($meta)*])* - $kind($ty), - $into_ref, - $into_mut, - $borrow_ref, - $borrow_mut, - } - - $(#[$($meta)*])* - /// - /// This clones the underlying value. - #[inline] - pub fn $as(&self) -> Result<$ty, RuntimeError> { - let value = match self.borrow_ref_repr()? { - BorrowRefRepr::Mutable(value) => value, - value => { - return Err(RuntimeError::expected::<$ty>(value.type_info())); - } - }; - - match &*value { - Mutable::$kind(value) => Ok(value.clone()), - value => { - Err(RuntimeError::expected::<$ty>(value.type_info())) - } - } - } - } -} - macro_rules! from { ($($variant:ident => $ty:ty),* $(,)*) => { $( @@ -358,30 +317,6 @@ macro_rules! inline_from { }; } -macro_rules! from_container { - ($($variant:ident => $ty:ty),* $(,)?) => { - $( - impl TryFrom<$ty> for Value { - type Error = alloc::Error; - - #[inline] - fn try_from(value: $ty) -> Result { - Value::try_from(Mutable::$variant(value)) - } - } - - impl IntoOutput for $ty { - type Output = $ty; - - #[inline] - fn into_output(self) -> VmResult { - VmResult::Ok(self) - } - } - )* - }; -} - macro_rules! signed_value_trait { ($($ty:ty),* $(,)?) => { $( diff --git a/crates/rune/src/runtime/value/serde.rs b/crates/rune/src/runtime/value/serde.rs index 3bc632316..6a00f4968 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::{self, BorrowRefRepr, Bytes, Inline, Mutable, Object, OwnedTuple, Vec}; +use crate::runtime::{self, Bytes, Inline, Mutable, Object, OwnedTuple, ReprRef, Vec}; use crate::TypeHash; use serde::de::{self, Deserialize as _, Error as _}; @@ -26,8 +26,8 @@ impl ser::Serialize for Value { where S: ser::Serializer, { - match self.borrow_ref_repr().map_err(S::Error::custom)? { - BorrowRefRepr::Inline(value) => match *value { + match self.as_ref().map_err(S::Error::custom)? { + ReprRef::Inline(value) => match *value { Inline::Unit => serializer.serialize_unit(), Inline::Bool(value) => serializer.serialize_bool(value), Inline::Char(value) => serializer.serialize_char(value), @@ -37,8 +37,7 @@ impl ser::Serialize for Value { Inline::Type(..) => Err(ser::Error::custom("cannot serialize types")), Inline::Ordering(..) => Err(ser::Error::custom("cannot serialize orderings")), }, - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Option(option) => >::serialize(option, serializer), + ReprRef::Mutable(value) => match &*value.borrow_ref().map_err(S::Error::custom)? { Mutable::EmptyStruct(..) => { Err(ser::Error::custom("cannot serialize empty structs")) } @@ -47,9 +46,14 @@ impl ser::Serialize for Value { } Mutable::Struct(..) => Err(ser::Error::custom("cannot serialize objects structs")), Mutable::Variant(..) => Err(ser::Error::custom("cannot serialize variants")), - Mutable::Result(..) => Err(ser::Error::custom("cannot serialize results")), }, - BorrowRefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { + Option::::HASH => { + let option = value + .borrow_ref::>() + .map_err(S::Error::custom)?; + >::serialize(&option, serializer) + } String::HASH => { let string = value.borrow_ref::().map_err(S::Error::custom)?; serializer.serialize_str(string.as_str()) diff --git a/crates/rune/src/runtime/variant.rs b/crates/rune/src/runtime/variant.rs index 3b0c96b1b..e079d577a 100644 --- a/crates/rune/src/runtime/variant.rs +++ b/crates/rune/src/runtime/variant.rs @@ -8,7 +8,7 @@ use crate::alloc::clone::TryClone; use crate::alloc::Box; use super::{ - Accessor, FromValue, Mutable, OwnedRepr, OwnedTuple, ProtocolCaller, RuntimeError, Tuple, + Accessor, FromValue, Mutable, OwnedTuple, ProtocolCaller, ReprOwned, RuntimeError, Tuple, TypeInfo, Value, VariantRtti, Vec, VmResult, }; @@ -179,10 +179,10 @@ impl Variant { impl FromValue for Variant { fn from_value(value: Value) -> Result { match value.take_repr()? { - OwnedRepr::Inline(value) => Err(RuntimeError::expected_variant(value.type_info())), - OwnedRepr::Mutable(Mutable::Variant(value)) => Ok(value), - OwnedRepr::Mutable(value) => Err(RuntimeError::expected_variant(value.type_info())), - OwnedRepr::Any(value) => Err(RuntimeError::expected_variant(value.type_info())), + 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())), } } } diff --git a/crates/rune/src/runtime/vec.rs b/crates/rune/src/runtime/vec.rs index dc90067c7..80540e76c 100644 --- a/crates/rune/src/runtime/vec.rs +++ b/crates/rune/src/runtime/vec.rs @@ -535,7 +535,7 @@ where T: FromValue, { fn from_value(value: Value) -> Result { - let vec = value.into_any::()?; + let vec = value.downcast::()?; let mut output = ::rust_alloc::vec::Vec::with_capacity(vec.len()); @@ -552,7 +552,7 @@ where T: FromValue, { fn from_value(value: Value) -> Result { - let vec = value.into_any::()?; + let vec = value.downcast::()?; let mut output = alloc::Vec::try_with_capacity(vec.len())?; @@ -568,7 +568,7 @@ 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_any_ref::()); + let vec = vm_try!(value.into_ref::()); let (vec, guard) = Ref::into_raw(vec); 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 81595cd94..51bc13768 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_any_ref::<$crate::runtime::Vec>()?; + let vec = value.into_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 2c55c74be..34c96c61a 100644 --- a/crates/rune/src/runtime/vm.rs +++ b/crates/rune/src/runtime/vm.rs @@ -3,7 +3,6 @@ use core::fmt; use core::mem::replace; use core::ops; use core::ptr::NonNull; -use core::slice; use ::rust_alloc::sync::Arc; @@ -16,14 +15,14 @@ use crate::modules::{option, result}; use crate::runtime; use super::{ - budget, Args, Awaited, BorrowMut, BorrowRefRepr, Bytes, Call, ControlFlow, DynArgs, - DynGuardedArgs, EmptyStruct, Format, FormatSpec, Formatter, FromValue, Function, Future, - Generator, GeneratorState, GuardedArgs, Inline, Inst, InstAddress, InstAssignOp, InstOp, - InstRange, InstTarget, InstValue, InstVariant, MutRepr, Mutable, Object, Output, OwnedTuple, - Pair, Panic, Protocol, ProtocolCaller, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, - RangeToInclusive, RefRepr, RuntimeContext, Select, SelectFuture, Stack, Stream, Struct, Type, - TypeCheck, TypeHash, TypeInfo, TypeOf, Unit, UnitFn, UnitStorage, Value, Variant, VariantData, - Vec, VmDiagnostics, VmDiagnosticsObj, VmError, VmErrorKind, VmExecution, VmHalt, VmIntegerRepr, + budget, Args, Awaited, BorrowMut, Bytes, Call, ControlFlow, DynArgs, DynGuardedArgs, + EmptyStruct, Format, FormatSpec, Formatter, FromValue, Function, Future, Generator, + 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, + VmDiagnostics, VmDiagnosticsObj, VmError, VmErrorKind, VmExecution, VmHalt, VmIntegerRepr, VmResult, VmSendExecution, }; @@ -470,12 +469,12 @@ impl Vm { /// # Panics /// /// If any of the arguments passed in are references, and that references is - /// captured somewhere in the call as [`Mut`] or [`Ref`] - /// this call will panic as we are trying to free the metadata relatedc to - /// the reference. + /// captured somewhere in the call as [`Mut`] or [`Ref`] this call + /// will panic as we are trying to free the metadata relatedc to the + /// reference. /// - /// [`Mut`]: runtime::Mut - /// [`Ref`]: runtime::Ref + /// [`Mut`]: crate::Mut + /// [`Ref`]: crate::Ref pub fn call( &mut self, name: impl ToTypeHash, @@ -510,12 +509,12 @@ impl Vm { /// # Panics /// /// If any of the arguments passed in are references, and that references is - /// captured somewhere in the call as [`Mut`] or [`Ref`] - /// this call will panic as we are trying to free the metadata relatedc to - /// the reference. + /// captured somewhere in the call as [`Mut`] or [`Ref`] this call + /// will panic as we are trying to free the metadata relatedc to the + /// reference. /// - /// [`Mut`]: runtime::Mut - /// [`Ref`]: runtime::Ref + /// [`Mut`]: crate::Mut + /// [`Ref`]: crate::Ref pub fn call_with_diagnostics( &mut self, name: impl ToTypeHash, @@ -824,9 +823,9 @@ impl Vm { /// Implementation of getting a string index on an object-like type. fn try_object_like_index_get(target: &Value, field: &str) -> VmResult> { - match vm_try!(target.as_ref_repr()) { - RefRepr::Inline(..) => VmResult::Ok(None), - RefRepr::Mutable(target) => { + match vm_try!(target.as_ref()) { + ReprRef::Inline(..) => VmResult::Ok(None), + ReprRef::Mutable(target) => { let target = vm_try!(target.borrow_ref()); let value = match &*target { @@ -847,7 +846,7 @@ impl Vm { VmResult::Ok(Some(value.clone())) } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { Object::HASH => { let target = vm_try!(value.borrow_ref::()); @@ -867,35 +866,46 @@ impl Vm { /// Implementation of getting a string index on an object-like type. fn try_tuple_like_index_get(target: &Value, index: usize) -> VmResult> { - let result = match vm_try!(target.borrow_ref_repr()) { - BorrowRefRepr::Inline(target) => match target { + let result = match vm_try!(target.as_ref()) { + ReprRef::Inline(target) => match target { Inline::Unit => Err(target.type_info()), _ => return VmResult::Ok(None), }, - BorrowRefRepr::Mutable(target) => match &*target { - Mutable::Result(result) => match (index, result) { - (0, Ok(value)) => Ok(value.clone()), - (0, Err(value)) => Ok(value.clone()), - _ => Err(target.type_info()), - }, - Mutable::Option(option) => match (index, option) { - (0, Some(value)) => Ok(value.clone()), - _ => Err(target.type_info()), - }, - Mutable::TupleStruct(tuple_struct) => match tuple_struct.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) { + ReprRef::Mutable(target) => { + let target = vm_try!(target.borrow_ref()); + + match &*target { + Mutable::TupleStruct(tuple_struct) => match tuple_struct.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), - }, - _ => return VmResult::Ok(None), - }, - BorrowRefRepr::Any(target) => match target.type_hash() { + } + } + ReprRef::Any(target) => match target.type_hash() { + Result::::HASH => { + match ( + index, + &*vm_try!(target.borrow_ref::>()), + ) { + (0, Ok(value)) => Ok(value.clone()), + (0, Err(value)) => Ok(value.clone()), + _ => Err(target.type_info()), + } + } + Option::::HASH => { + match (index, &*vm_try!(target.borrow_ref::>())) { + (0, Some(value)) => Ok(value.clone()), + _ => Err(target.type_info()), + } + } GeneratorState::HASH => match (index, &*vm_try!(target.borrow_ref())) { (0, GeneratorState::Yielded(value)) => Ok(value.clone()), (0, GeneratorState::Complete(value)) => Ok(value.clone()), @@ -937,21 +947,12 @@ impl Vm { target: &Value, index: usize, ) -> VmResult>> { - match vm_try!(target.as_ref_repr()) { - RefRepr::Mutable(value) => { + match vm_try!(target.as_ref()) { + ReprRef::Mutable(value) => { let mut unsupported = false; let result = BorrowMut::try_map(vm_try!(value.borrow_mut()), |kind| { match kind { - Mutable::Result(result) => match (index, result) { - (0, Ok(value)) => return Some(value), - (0, Err(value)) => return Some(value), - _ => return None, - }, - Mutable::Option(option) => match (index, option) { - (0, Some(value)) => return Some(value), - _ => return None, - }, Mutable::TupleStruct(tuple_struct) => return tuple_struct.get_mut(index), Mutable::Variant(Variant { data: VariantData::Tuple(tuple), @@ -978,7 +979,44 @@ impl Vm { }), } } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { + Result::::HASH => { + let result = BorrowMut::try_map( + vm_try!(value.borrow_mut::>()), + |value| match (index, value) { + (0, Ok(value)) => Some(value), + (0, Err(value)) => Some(value), + _ => None, + }, + ); + + if let Ok(value) = result { + return VmResult::Ok(Some(value)); + } + + err(VmErrorKind::MissingIndexInteger { + target: TypeInfo::any::>(), + index: VmIntegerRepr::from(index), + }) + } + Option::::HASH => { + let result = + BorrowMut::try_map(vm_try!(value.borrow_mut::>()), |value| { + match (index, value) { + (0, Some(value)) => Some(value), + _ => None, + } + }); + + if let Ok(value) = result { + return VmResult::Ok(Some(value)); + } + + err(VmErrorKind::MissingIndexInteger { + target: TypeInfo::any::>(), + index: VmIntegerRepr::from(index), + }) + } GeneratorState::HASH => { let result = BorrowMut::try_map( vm_try!(value.borrow_mut::()), @@ -1035,12 +1073,12 @@ impl Vm { target: &'a Value, field: &str, ) -> VmResult>> { - match vm_try!(target.as_ref_repr()) { - RefRepr::Inline(actual) => err(VmErrorKind::MissingField { + match vm_try!(target.as_ref()) { + ReprRef::Inline(actual) => err(VmErrorKind::MissingField { target: actual.type_info(), field: vm_try!(field.try_to_owned()), }), - RefRepr::Mutable(target) => { + ReprRef::Mutable(target) => { let target = vm_try!(target.borrow_mut()); let mut unsupported = false; @@ -1076,7 +1114,7 @@ impl Vm { }), } } - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { Object::HASH => { let object = vm_try!(value.borrow_mut::()); @@ -1096,31 +1134,12 @@ impl Vm { /// Implementation of getting a string index on an object-like type. 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 { + match vm_try!(target.as_ref()) { + ReprRef::Inline(target) => match target { Inline::Unit => VmResult::Ok(false), _ => VmResult::Ok(false), }, - RefRepr::Mutable(target) => match &mut *vm_try!(target.borrow_mut()) { - Mutable::Result(result) => { - let target = match result { - Ok(ok) if index == 0 => ok, - Err(err) if index == 1 => err, - _ => return VmResult::Ok(false), - }; - - target.clone_from(from); - VmResult::Ok(true) - } - Mutable::Option(option) => { - let target = match option { - Some(some) if index == 0 => some, - _ => return VmResult::Ok(false), - }; - - target.clone_from(from); - VmResult::Ok(true) - } + ReprRef::Mutable(target) => match &mut *vm_try!(target.borrow_mut()) { Mutable::TupleStruct(tuple_struct) => { if let Some(target) = tuple_struct.get_mut(index) { target.clone_from(from); @@ -1141,7 +1160,30 @@ impl Vm { } _ => VmResult::Ok(false), }, - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { + Result::::HASH => { + let mut result = vm_try!(value.borrow_mut::>()); + + let target = match &mut *result { + Ok(ok) if index == 0 => ok, + Err(err) if index == 1 => err, + _ => return VmResult::Ok(false), + }; + + target.clone_from(from); + VmResult::Ok(true) + } + Option::::HASH => { + let mut option = vm_try!(value.borrow_mut::>()); + + let target = match &mut *option { + Some(some) if index == 0 => some, + _ => return VmResult::Ok(false), + }; + + target.clone_from(from); + VmResult::Ok(true) + } runtime::Vec::HASH => { let mut vec = vm_try!(value.borrow_mut::()); @@ -1177,11 +1219,11 @@ impl Vm { let index = vm_try!(self.unit.lookup_string(slot)); 'fallback: { - match vm_try!(target.as_ref_repr()) { - RefRepr::Inline(..) => { + match vm_try!(target.as_ref()) { + ReprRef::Inline(..) => { return VmResult::Ok(CallResult::Unsupported(target.clone())); } - RefRepr::Mutable(target) => match *vm_try!(target.borrow_ref()) { + 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())); @@ -1202,7 +1244,7 @@ impl Vm { break 'fallback; } }, - RefRepr::Any(value) => match value.type_hash() { + ReprRef::Any(value) => match value.type_hash() { Object::HASH => { let object = vm_try!(value.borrow_ref::()); @@ -1224,12 +1266,12 @@ impl Vm { } fn try_object_slot_index_set(target: &Value, field: &str, value: &Value) -> VmResult { - match vm_try!(target.as_ref_repr()) { - RefRepr::Inline(target) => err(VmErrorKind::MissingField { + match vm_try!(target.as_ref()) { + ReprRef::Inline(target) => err(VmErrorKind::MissingField { target: target.type_info(), field: vm_try!(field.try_to_owned()), }), - RefRepr::Mutable(target) => { + ReprRef::Mutable(target) => { let mut target = vm_try!(target.borrow_mut()); match &mut *target { @@ -1257,7 +1299,7 @@ impl Vm { field: vm_try!(field.try_to_owned()), }) } - RefRepr::Any(target) => match target.type_hash() { + ReprRef::Any(target) => match target.type_hash() { Object::HASH => { let key = vm_try!(field.try_to_owned()); let mut object = vm_try!(target.borrow_mut::()); @@ -1273,25 +1315,13 @@ impl Vm { where F: FnOnce(&[Value]) -> O, { - let value = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => match (ty, value) { + let value = match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match (ty, value) { (TypeCheck::Unit, Inline::Unit) => Some(f(&[])), _ => None, }, - BorrowRefRepr::Mutable(value) => match (ty, &*value) { - (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))), - _ => None, - }, - (TypeCheck::Option(v), Mutable::Option(option)) => match (v, option) { - (0, Some(some)) => Some(f(slice::from_ref(some))), - (1, None) => Some(f(&[])), - _ => None, - }, - _ => None, - }, - BorrowRefRepr::Any(value) => match (ty, value.type_hash()) { + ReprRef::Mutable(..) => None, + ReprRef::Any(value) => match (ty, value.type_hash()) { (TypeCheck::Vec, runtime::Vec::HASH) => { let vec = vm_try!(value.borrow_ref::()); Some(f(&vec)) @@ -1312,7 +1342,7 @@ impl Vm { let b = vm_try!(self.stack.at(rhs)); let a = vm_try!(self.stack.at(lhs)); - let RefRepr::Inline(Inline::Type(ty)) = vm_try!(b.as_ref_repr()) else { + let ReprRef::Inline(Inline::Type(ty)) = vm_try!(b.as_ref()) else { return err(VmErrorKind::UnsupportedIs { value: vm_try!(a.type_info()), test_type: vm_try!(b.type_info()), @@ -1335,10 +1365,10 @@ impl Vm { }; } - let value = match vm_try!(a.as_ref_repr()) { - RefRepr::Inline(Inline::Unsigned(a)) => convert!(u64, *a), - RefRepr::Inline(Inline::Signed(a)) => convert!(i64, *a), - RefRepr::Inline(Inline::Float(a)) => convert!(f64, *a), + let value = match vm_try!(a.as_ref()) { + ReprRef::Inline(Inline::Unsigned(a)) => convert!(u64, *a), + ReprRef::Inline(Inline::Signed(a)) => convert!(i64, *a), + ReprRef::Inline(Inline::Float(a)) => convert!(f64, *a), value => { return err(VmErrorKind::UnsupportedAs { value: vm_try!(value.type_info()), @@ -1376,8 +1406,8 @@ impl Vm { let rhs = vm_try!(self.stack.at(rhs)); let lhs = vm_try!(self.stack.at(lhs)); - let inline = match (vm_try!(lhs.as_ref_repr()), vm_try!(rhs.as_ref_repr())) { - (RefRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + let inline = match (vm_try!(lhs.as_ref()), vm_try!(rhs.as_ref())) { + (ReprRef::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Bool(lhs), Inline::Bool(rhs)) => Inline::Bool(bool_op(*lhs, *rhs)), (lhs, rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { @@ -1517,23 +1547,23 @@ impl Vm { let fallback = match target_value!(self, target, guard, lhs, rhs) { TargetValue::Same(value) => { - match vm_try!(value.as_mut_repr()) { - MutRepr::Inline(Inline::Signed(value)) => { + match vm_try!(value.as_mut()) { + ReprMut::Inline(Inline::Signed(value)) => { let out = vm_try!(signed_op(*value, *value).ok_or_else(error)); *value = out; return VmResult::Ok(()); } - MutRepr::Inline(Inline::Unsigned(value)) => { + ReprMut::Inline(Inline::Unsigned(value)) => { let out = vm_try!(unsigned_op(*value, *value).ok_or_else(error)); *value = out; return VmResult::Ok(()); } - MutRepr::Inline(Inline::Float(value)) => { + ReprMut::Inline(Inline::Float(value)) => { let out = float_op(*value, *value); *value = out; return VmResult::Ok(()); } - MutRepr::Inline(value) => { + ReprMut::Inline(value) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: value.type_info(), @@ -1546,8 +1576,8 @@ impl Vm { TargetFallback::Value(value.clone(), value.clone()) } TargetValue::Pair(lhs, rhs) => { - match (vm_try!(lhs.as_mut_repr()), vm_try!(rhs.as_ref_repr())) { - (MutRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + match (vm_try!(lhs.as_mut()), vm_try!(rhs.as_ref())) { + (ReprMut::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Signed(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); let out = vm_try!(signed_op(*lhs, rhs).ok_or_else(error)); @@ -1573,7 +1603,7 @@ impl Vm { }); } }, - (MutRepr::Inline(lhs), rhs) => { + (ReprMut::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -1673,8 +1703,8 @@ impl Vm { let lhs = vm_try!(self.stack.at(lhs)); 'fallback: { - let inline = match (vm_try!(lhs.as_ref_repr()), vm_try!(rhs.as_ref_repr())) { - (RefRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + let inline = match (vm_try!(lhs.as_ref()), vm_try!(rhs.as_ref())) { + (ReprRef::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Unsigned(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); Inline::Unsigned(vm_try!(unsigned_op(*lhs, rhs).ok_or_else(error))) @@ -1692,7 +1722,7 @@ impl Vm { }); } }, - (RefRepr::Inline(lhs), rhs) => { + (ReprRef::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -1742,8 +1772,8 @@ impl Vm { let rhs = vm_try!(self.stack.at(rhs)); 'fallback: { - let inline = match (vm_try!(lhs.as_ref_repr()), vm_try!(rhs.as_ref_repr())) { - (RefRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + let inline = match (vm_try!(lhs.as_ref()), vm_try!(rhs.as_ref())) { + (ReprRef::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Unsigned(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); Inline::Unsigned(unsigned_op(*lhs, rhs)) @@ -1761,7 +1791,7 @@ impl Vm { }); } }, - (RefRepr::Inline(lhs), rhs) => { + (ReprRef::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -1809,23 +1839,23 @@ impl Vm { let fallback = match target_value!(self, target, guard, lhs, rhs) { TargetValue::Same(value) => { - match vm_try!(value.as_mut_repr()) { - MutRepr::Inline(Inline::Unsigned(value)) => { + match vm_try!(value.as_mut()) { + ReprMut::Inline(Inline::Unsigned(value)) => { let rhs = *value; unsigned_op(value, rhs); return VmResult::Ok(()); } - MutRepr::Inline(Inline::Signed(value)) => { + ReprMut::Inline(Inline::Signed(value)) => { let rhs = *value; signed_op(value, rhs); return VmResult::Ok(()); } - MutRepr::Inline(Inline::Bool(value)) => { + ReprMut::Inline(Inline::Bool(value)) => { let rhs = *value; bool_op(value, rhs); return VmResult::Ok(()); } - MutRepr::Inline(value) => { + ReprMut::Inline(value) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: value.type_info(), @@ -1838,8 +1868,8 @@ impl Vm { TargetFallback::Value(value.clone(), value.clone()) } TargetValue::Pair(lhs, rhs) => { - match (vm_try!(lhs.as_mut_repr()), vm_try!(rhs.as_ref_repr())) { - (MutRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + match (vm_try!(lhs.as_mut()), vm_try!(rhs.as_ref())) { + (ReprMut::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Unsigned(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); unsigned_op(lhs, rhs); @@ -1862,7 +1892,7 @@ impl Vm { }); } }, - (MutRepr::Inline(lhs), rhs) => { + (ReprMut::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -1894,7 +1924,7 @@ impl Vm { let inline = 'inline: { match vm_try!(self.stack.pair(lhs, rhs)) { Pair::Same(value) => { - if let MutRepr::Inline(lhs) = vm_try!(value.as_mut_repr()) { + if let ReprMut::Inline(lhs) = vm_try!(value.as_mut()) { match lhs { Inline::Unsigned(value) => { let shift = @@ -1922,8 +1952,8 @@ impl Vm { break 'fallback (value.clone(), value.clone()); } Pair::Pair(lhs, rhs) => { - match (vm_try!(lhs.as_mut_repr()), vm_try!(rhs.as_ref_repr())) { - (MutRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + match (vm_try!(lhs.as_mut()), vm_try!(rhs.as_ref())) { + (ReprMut::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Unsigned(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); let value = vm_try!(unsigned_op(*lhs, rhs).ok_or_else(error)); @@ -1942,7 +1972,7 @@ impl Vm { }); } }, - (MutRepr::Inline(lhs), rhs) => { + (ReprMut::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -1990,20 +2020,20 @@ impl Vm { let fallback = match target_value!(self, target, guard, lhs, rhs) { TargetValue::Same(value) => { - match vm_try!(value.as_mut_repr()) { - MutRepr::Inline(Inline::Unsigned(value)) => { + match vm_try!(value.as_mut()) { + ReprMut::Inline(Inline::Unsigned(value)) => { let shift = vm_try!(u32::try_from(*value).ok().ok_or_else(error)); let out = vm_try!(unsigned_op(*value, shift).ok_or_else(error)); *value = out; return VmResult::Ok(()); } - MutRepr::Inline(Inline::Signed(value)) => { + ReprMut::Inline(Inline::Signed(value)) => { let shift = vm_try!(u32::try_from(*value).ok().ok_or_else(error)); let out = vm_try!(signed_op(*value, shift).ok_or_else(error)); *value = out; return VmResult::Ok(()); } - MutRepr::Inline(value) => { + ReprMut::Inline(value) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: value.type_info(), @@ -2016,8 +2046,8 @@ impl Vm { TargetFallback::Value(value.clone(), value.clone()) } TargetValue::Pair(lhs, rhs) => { - match (vm_try!(lhs.as_mut_repr()), vm_try!(rhs.as_ref_repr())) { - (MutRepr::Inline(lhs), RefRepr::Inline(rhs)) => match (lhs, rhs) { + match (vm_try!(lhs.as_mut()), vm_try!(rhs.as_ref())) { + (ReprMut::Inline(lhs), ReprRef::Inline(rhs)) => match (lhs, rhs) { (Inline::Unsigned(lhs), rhs) => { let rhs = vm_try!(rhs.as_integer()); let out = vm_try!(unsigned_op(*lhs, rhs).ok_or_else(error)); @@ -2038,7 +2068,7 @@ impl Vm { }); } }, - (MutRepr::Inline(lhs), rhs) => { + (ReprMut::Inline(lhs), rhs) => { return err(VmErrorKind::UnsupportedBinaryOperation { op: protocol.name, lhs: lhs.type_info(), @@ -2071,7 +2101,7 @@ impl Vm { let futures = futures_util::stream::FuturesUnordered::new(); for (branch, value) in vm_try!(self.stack.slice_at(addr, len)).iter().enumerate() { - let future = vm_try!(value.clone().into_any_mut::()); + let future = vm_try!(value.clone().into_mut::()); if !future.is_completed() { futures.push(SelectFuture::new(self.ip + branch, future)); @@ -2228,8 +2258,8 @@ impl Vm { fn op_not(&mut self, operand: InstAddress, out: Output) -> VmResult<()> { let value = vm_try!(self.stack.at(operand)); - let value = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => match value { + let value = match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Bool(value) => Value::from(!value), Inline::Unsigned(value) => Value::from(!value), Inline::Signed(value) => Value::from(!value), @@ -2239,7 +2269,7 @@ impl Vm { } }, actual => { - let operand = actual.type_info(); + let operand = vm_try!(actual.type_info()); return err(VmErrorKind::UnsupportedUnaryOperation { op: "!", operand }); } }; @@ -2252,8 +2282,8 @@ impl Vm { fn op_neg(&mut self, addr: InstAddress, out: Output) -> VmResult<()> { let value = vm_try!(self.stack.at(addr)); - let value = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => match value { + let value = match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match value { Inline::Float(value) => Value::from(-value), Inline::Signed(value) => Value::from(-value), actual => { @@ -2262,7 +2292,7 @@ impl Vm { } }, actual => { - let operand = actual.type_info(); + let operand = vm_try!(actual.type_info()); return err(VmErrorKind::UnsupportedUnaryOperation { op: "-", operand }); } }; @@ -2756,15 +2786,15 @@ impl Vm { let index = vm_try!(self.stack.at(index)); let target = vm_try!(self.stack.at(target)); - match vm_try!(index.as_ref_repr()) { - RefRepr::Inline(inline) => { + match vm_try!(index.as_ref()) { + ReprRef::Inline(inline) => { let index = vm_try!(inline.as_integer::()); if let Some(value) = vm_try!(Self::try_tuple_like_index_get(target, index)) { break 'store value; } } - RefRepr::Any(value) => { + ReprRef::Any(value) => { if let Some(index) = vm_try!(value.try_borrow_ref::()) { if let Some(value) = vm_try!(Self::try_object_like_index_get(target, index.as_str())) @@ -3110,10 +3140,16 @@ impl Vm { let value = { let value = vm_try!(self.stack.at(addr)); - if let BorrowRefRepr::Mutable(value) = vm_try!(value.borrow_ref_repr()) { - match &*value { - Mutable::Result(result) => break 'out vm_try!(result::result_try(result)), - Mutable::Option(option) => break 'out vm_try!(option::option_try(option)), + if let ReprRef::Any(value) = vm_try!(value.as_ref()) { + match value.type_hash() { + Result::::HASH => { + let result = vm_try!(value.borrow_ref::>()); + break 'out vm_try!(result::result_try(&result)); + } + Option::::HASH => { + let option = vm_try!(value.borrow_ref::>()); + break 'out vm_try!(option::option_try(&option)); + } _ => {} } } @@ -3273,35 +3309,41 @@ impl Vm { let value = vm_try!(self.stack.at(addr)); let is_match = 'out: { - match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Mutable(value) => match (enum_hash, &*value) { - (hash!(::std::result::Result), Mutable::Result(result)) => { - break 'out match (variant_hash, result) { + 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.enum_hash == enum_hash && rtti.hash == variant_hash; + } + _ => { + break 'out false; + } + }, + ReprRef::Any(any) => match enum_hash { + Result::::HASH => { + let result = vm_try!(any.borrow_ref::>()); + + break 'out match (variant_hash, &*result) { (hash!(::std::result::Result::Ok), Ok(..)) => true, (hash!(::std::result::Result::Err), Err(..)) => true, _ => false, }; } - (hash!(::std::option::Option), Mutable::Option(option)) => { - break 'out match (variant_hash, option) { + Option::::HASH => { + let option = vm_try!(any.borrow_ref::>()); + + break 'out match (variant_hash, &*option) { (hash!(::std::option::Option::None), None) => true, (hash!(::std::option::Option::Some), Some(..)) => true, _ => false, }; } - (enum_hash, Mutable::Variant(variant)) => { - let rtti = variant.rtti(); - break 'out rtti.enum_hash == enum_hash && rtti.hash == variant_hash; - } _ => { - break 'out false; + if any.type_hash() != enum_hash { + break 'out false; + } } }, - BorrowRefRepr::Any(any) => { - if any.type_hash() != enum_hash { - break 'out false; - } - } _ => { break 'out false; } @@ -3332,25 +3374,13 @@ impl Vm { ) -> VmResult<()> { let value = vm_try!(self.stack.at(addr)); - let is_match = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(value) => match (type_check, value) { + let is_match = match vm_try!(value.as_ref()) { + ReprRef::Inline(value) => match (type_check, value) { (TypeCheck::Unit, Inline::Unit) => true, _ => false, }, - BorrowRefRepr::Mutable(value) => match (type_check, &*value) { - (TypeCheck::Result(v), Mutable::Result(result)) => match (v, result) { - (0, Ok(..)) => true, - (1, Err(..)) => true, - _ => false, - }, - (TypeCheck::Option(v), Mutable::Option(option)) => match (v, option) { - (0, Some(..)) => true, - (1, None) => true, - _ => false, - }, - _ => false, - }, - BorrowRefRepr::Any(value) => match (type_check, value.type_hash()) { + ReprRef::Mutable(..) => false, + ReprRef::Any(value) => match (type_check, value.type_hash()) { (TypeCheck::Vec, runtime::Vec::HASH) => true, (TypeCheck::Tuple, runtime::OwnedTuple::HASH) => true, _ => false, @@ -3650,14 +3680,14 @@ impl Vm { return VmResult::Ok(None); } - match vm_try!(function.as_ref_repr()) { - RefRepr::Inline(value) => err(VmErrorKind::UnsupportedCallFn { + match vm_try!(function.as_ref()) { + ReprRef::Inline(value) => err(VmErrorKind::UnsupportedCallFn { actual: value.type_info(), }), - RefRepr::Mutable(value) => err(VmErrorKind::UnsupportedCallFn { + ReprRef::Mutable(value) => err(VmErrorKind::UnsupportedCallFn { actual: vm_try!(value.borrow_ref()).type_info(), }), - RefRepr::Any(value) => { + ReprRef::Any(value) => { let value = value.clone(); let f = vm_try!(value.borrow_ref::()); f.call_with_vm(self, addr, args, out) @@ -3669,24 +3699,27 @@ impl Vm { fn op_iter_next(&mut self, addr: InstAddress, jump: usize, out: Output) -> VmResult<()> { let value = vm_try!(self.stack.at(addr)); - let some = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Option(option) => match option { - Some(some) => some.clone(), - None => { + let some = match vm_try!(value.as_ref()) { + ReprRef::Any(value) => match value.type_hash() { + Option::::HASH => { + let option = vm_try!(value.borrow_ref::>()); + + let Some(some) = &*option else { self.ip = vm_try!(self.unit.translate(jump)); return VmResult::Ok(()); - } - }, - actual => { + }; + + some.clone() + } + _ => { return err(VmErrorKind::UnsupportedIterNextOperand { - actual: actual.type_info(), + actual: value.type_info(), }); } }, actual => { return err(VmErrorKind::UnsupportedIterNextOperand { - actual: actual.type_info(), + actual: vm_try!(actual.type_info()), }); } }; diff --git a/crates/rune/src/tests.rs b/crates/rune/src/tests.rs index 734065fd1..d165aa647 100644 --- a/crates/rune/src/tests.rs +++ b/crates/rune/src/tests.rs @@ -17,7 +17,7 @@ pub(crate) mod prelude { pub(crate) use crate::parse; pub(crate) use crate::runtime::{ self, Bytes, Formatter, Function, InstAddress, MaybeTypeOf, Mutable, Object, Output, - OwnedRepr, OwnedTuple, Protocol, RawAnyGuard, Ref, Stack, Tuple, TupleStruct, TypeHash, + OwnedTuple, Protocol, RawAnyGuard, Ref, ReprOwned, Stack, Tuple, TupleStruct, TypeHash, TypeInfo, TypeOf, UnsafeToRef, Variant, VecTuple, VmErrorKind, VmResult, }; pub(crate) use crate::support::Result; diff --git a/crates/rune/src/tests/bug_344.rs b/crates/rune/src/tests/bug_344.rs index ea5b02702..d4d3fb9a1 100644 --- a/crates/rune/src/tests/bug_344.rs +++ b/crates/rune/src/tests/bug_344.rs @@ -192,7 +192,7 @@ impl UnsafeToRef for GuardCheck { type Guard = Guard; unsafe fn unsafe_to_ref<'a>(value: Value) -> VmResult<(&'a Self, Self::Guard)> { - let (output, guard) = Ref::into_raw(vm_try!(value.into_any_ref::())); + let (output, guard) = Ref::into_raw(vm_try!(value.into_ref::())); let guard = Guard { guard, diff --git a/crates/rune/src/tests/vm_function.rs b/crates/rune/src/tests/vm_function.rs index c93376aec..3bf06d34f 100644 --- a/crates/rune/src/tests/vm_function.rs +++ b/crates/rune/src/tests/vm_function.rs @@ -36,7 +36,7 @@ fn test_function() { let value: Value = function.call((1i64,)).unwrap(); assert!(matches!( value.take_repr().unwrap(), - OwnedRepr::Mutable(Mutable::Variant(..)) + ReprOwned::Mutable(Mutable::Variant(..)) )); // ptr to dynamic function. @@ -49,7 +49,7 @@ fn test_function() { let value: Value = function.call((1i64,)).unwrap(); assert!(matches!( value.take_repr().unwrap(), - OwnedRepr::Mutable(Mutable::TupleStruct(..)) + ReprOwned::Mutable(Mutable::TupleStruct(..)) )); // non-capturing closure == free function