From d37cadf9fca1539a29e52c8d444bd8ff6e68d1dc Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Fri, 1 Nov 2024 17:18:43 +0100 Subject: [PATCH] rune: Store Function in AnyObj instead of Mutable (relates #844) --- crates/rune/src/modules/ops.rs | 86 +++++++++++---------- crates/rune/src/modules/string.rs | 103 ++++++++++++------------- crates/rune/src/runtime/function.rs | 56 ++++++++++---- crates/rune/src/runtime/static_type.rs | 2 - crates/rune/src/runtime/value.rs | 28 ++----- crates/rune/src/runtime/value/serde.rs | 3 - crates/rune/src/runtime/vm.rs | 27 ++++--- 7 files changed, 153 insertions(+), 152 deletions(-) diff --git a/crates/rune/src/modules/ops.rs b/crates/rune/src/modules/ops.rs index c7111b3c6..456e6dfbe 100644 --- a/crates/rune/src/modules/ops.rs +++ b/crates/rune/src/modules/ops.rs @@ -5,9 +5,10 @@ pub mod generator; use core::cmp::Ordering; use once_cell::sync::OnceCell; -use rune_alloc::hash_map::RandomState; +use rune::item; use crate as rune; +use crate::alloc::hash_map::RandomState; use crate::runtime::range::RangeIter; use crate::runtime::range_from::RangeFromIter; use crate::runtime::range_inclusive::RangeInclusiveIter; @@ -71,16 +72,16 @@ pub fn module() -> Result { m.function_meta(RangeFrom::contains__meta)?; m.function_meta(RangeFrom::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(RangeFrom::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(RangeFrom::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(RangeFrom::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; iter!(RangeFromIter); } @@ -90,16 +91,16 @@ pub fn module() -> Result { m.function_meta(RangeFull::contains__meta)?; m.function_meta(RangeFull::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(RangeFull::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(RangeFull::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(RangeFull::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; } { @@ -109,16 +110,16 @@ pub fn module() -> Result { m.function_meta(RangeInclusive::contains__meta)?; m.function_meta(RangeInclusive::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(RangeInclusive::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(RangeInclusive::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(RangeInclusive::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; double_ended!(RangeInclusiveIter); } @@ -128,16 +129,16 @@ pub fn module() -> Result { m.function_meta(RangeToInclusive::contains__meta)?; m.function_meta(RangeToInclusive::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(RangeToInclusive::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(RangeToInclusive::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(RangeToInclusive::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; } { @@ -145,16 +146,16 @@ pub fn module() -> Result { m.function_meta(RangeTo::contains__meta)?; m.function_meta(RangeTo::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(RangeTo::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(RangeTo::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(RangeTo::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; } { @@ -164,16 +165,16 @@ pub fn module() -> Result { m.function_meta(Range::contains__meta)?; m.function_meta(Range::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(Range::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(Range::partial_cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialOrd))?; + m.implement_trait::(item!(::std::cmp::PartialOrd))?; m.function_meta(Range::cmp__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Ord))?; + m.implement_trait::(item!(::std::cmp::Ord))?; double_ended!(RangeIter); } @@ -182,29 +183,32 @@ pub fn module() -> Result { m.ty::()?; m.function_meta(ControlFlow::partial_eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::PartialEq))?; + m.implement_trait::(item!(::std::cmp::PartialEq))?; m.function_meta(ControlFlow::eq__meta)?; - m.implement_trait::(rune::item!(::std::cmp::Eq))?; + m.implement_trait::(item!(::std::cmp::Eq))?; m.function_meta(ControlFlow::debug_fmt__meta)?; m.function_meta(ControlFlow::clone__meta)?; - m.implement_trait::(rune::item!(::std::clone::Clone))?; + m.implement_trait::(item!(::std::clone::Clone))?; } m.ty::()?; + m.function_meta(Function::clone__meta)?; + m.implement_trait::(item!(::std::clone::Clone))?; + m.function_meta(Function::debug_fmt__meta)?; - m.function_meta(partial_eq)?; - m.function_meta(eq)?; - m.function_meta(partial_cmp)?; - m.function_meta(cmp)?; - m.function_meta(hash)?; + m.function_meta(partial_eq__meta)?; + m.function_meta(eq__meta)?; + m.function_meta(partial_cmp__meta)?; + m.function_meta(cmp__meta)?; + m.function_meta(hash__meta)?; - m.reexport(["Generator"], rune::item!(::std::ops::generator::Generator))?; + m.reexport(["Generator"], item!(::std::ops::generator::Generator))?; m.reexport( ["GeneratorState"], - rune::item!(::std::ops::generator::GeneratorState), + item!(::std::ops::generator::GeneratorState), )?; Ok(m) } @@ -228,7 +232,7 @@ pub fn module() -> Result { /// assert!(partial_eq(1.0, 1.0)); /// assert!(!partial_eq(1.0, 2.0)); /// ``` -#[rune::function] +#[rune::function(keep)] fn partial_eq(lhs: Value, rhs: Value) -> VmResult { Value::partial_eq(&lhs, &rhs) } @@ -251,7 +255,7 @@ fn partial_eq(lhs: Value, rhs: Value) -> VmResult { /// assert!(eq(1.0, 1.0)); /// assert!(!eq(1.0, 2.0)); /// ``` -#[rune::function] +#[rune::function(keep)] fn eq(lhs: Value, rhs: Value) -> VmResult { Value::eq(&lhs, &rhs) } @@ -278,7 +282,7 @@ fn eq(lhs: Value, rhs: Value) -> VmResult { /// assert_eq!(partial_cmp(1.0, 2.0), Some(Ordering::Less)); /// assert_eq!(partial_cmp(1.0, f64::NAN), None); /// ``` -#[rune::function] +#[rune::function(keep)] fn partial_cmp(lhs: Value, rhs: Value) -> VmResult> { Value::partial_cmp(&lhs, &rhs) } @@ -306,12 +310,12 @@ fn partial_cmp(lhs: Value, rhs: Value) -> VmResult> { /// assert_eq!(cmp(1, 1), Ordering::Equal); /// assert_eq!(cmp(1, 2), Ordering::Less); /// ``` -#[rune::function] +#[rune::function(keep)] fn cmp(lhs: Value, rhs: Value) -> VmResult { Value::cmp(&lhs, &rhs) } -/// Hashes the given value. +/// Hashes the given function. /// /// For non-builtin types this uses the [`HASH`] protocol. /// @@ -333,7 +337,7 @@ fn cmp(lhs: Value, rhs: Value) -> VmResult { /// /// assert_eq!(hash([1, 2]), hash((1, 2))); /// ``` -#[rune::function] +#[rune::function(keep)] fn hash(value: Value) -> VmResult { let state = STATE.get_or_init(RandomState::new); let mut hasher = Hasher::new_with(state); diff --git a/crates/rune/src/modules/string.rs b/crates/rune/src/modules/string.rs index 40b0aa4fc..ca43b976d 100644 --- a/crates/rune/src/modules/string.rs +++ b/crates/rune/src/modules/string.rs @@ -12,9 +12,9 @@ use crate::alloc::string::FromUtf8Error; use crate::alloc::{String, Vec}; use crate::compile::Named; use crate::runtime::{ - BorrowRefRepr, Bytes, Formatter, FromValue, Function, Hasher, Inline, MaybeTypeOf, Mutable, - Panic, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Ref, ToValue, - TypeOf, Value, VmErrorKind, VmResult, + Bytes, Formatter, FromValue, Function, Hasher, Inline, MaybeTypeOf, Panic, Range, RangeFrom, + RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Ref, RefRepr, ToValue, TypeOf, Value, + VmErrorKind, VmResult, }; use crate::{Any, ContextError, Module, TypeHash}; @@ -889,46 +889,40 @@ 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 { - let split = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(Inline::Char(c)) => { - vm_try!(rune::to_value(Split::new(this, *c))) + match vm_try!(value.as_ref_repr()) { + RefRepr::Inline(Inline::Char(c)) => { + VmResult::Ok(vm_try!(rune::to_value(Split::new(this, *c)))) } - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Function(ref f) => { - vm_try!(rune::to_value(Split::new(this, vm_try!(f.try_clone())))) - } - actual => { - return VmResult::err([ - VmErrorKind::expected::(actual.type_info()), - VmErrorKind::bad_argument(0), - ]) - } - }, - BorrowRefRepr::Any(value) => match value.type_hash() { + RefRepr::Inline(value) => VmResult::err([ + VmErrorKind::expected::(value.type_info()), + VmErrorKind::bad_argument(0), + ]), + RefRepr::Mutable(value) => VmResult::err([ + VmErrorKind::expected::(vm_try!(value.borrow_ref()).type_info()), + VmErrorKind::bad_argument(0), + ]), + RefRepr::Any(value) => match value.type_hash() { String::HASH => { let s = vm_try!(value.borrow_ref::()); - vm_try!(rune::to_value(Split::new( + let split = vm_try!(rune::to_value(Split::new( this, vm_try!(String::try_from(s.as_str())) - ))) + ))); + + VmResult::Ok(split) } - _ => { - return VmResult::err([ - VmErrorKind::expected::(value.type_info()), - VmErrorKind::bad_argument(0), - ]); + Function::HASH => { + let f = vm_try!(value.borrow_ref::()); + let split = vm_try!(rune::to_value(Split::new(this, vm_try!(f.try_clone())))); + VmResult::Ok(split) } - }, - value => { - return VmResult::err([ + _ => VmResult::err([ VmErrorKind::expected::(value.type_info()), VmErrorKind::bad_argument(0), - ]); - } - }; - - VmResult::Ok(split) + ]), + }, + } } /// Splits the string on the first occurrence of the specified delimiter and @@ -944,10 +938,27 @@ fn split(this: Ref, value: Value) -> VmResult { /// ``` #[rune::function(instance)] fn split_once(this: &str, value: Value) -> VmResult> { - let outcome = match vm_try!(value.borrow_ref_repr()) { - BorrowRefRepr::Inline(Inline::Char(pat)) => this.split_once(*pat), - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Function(f) => { + let outcome = match vm_try!(value.as_ref_repr()) { + RefRepr::Inline(Inline::Char(pat)) => this.split_once(*pat), + RefRepr::Inline(value) => { + return VmResult::err([ + VmErrorKind::expected::(value.type_info()), + VmErrorKind::bad_argument(0), + ]); + } + RefRepr::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() { + String::HASH => { + let s = vm_try!(value.borrow_ref::()); + this.split_once(s.as_str()) + } + Function::HASH => { + let f = vm_try!(value.borrow_ref::()); let mut err = None; let outcome = this.split_once(|c: char| match f.call::((c,)) { @@ -967,18 +978,6 @@ fn split_once(this: &str, value: Value) -> VmResult> { outcome } - actual => { - return VmResult::err([ - VmErrorKind::expected::(actual.type_info()), - VmErrorKind::bad_argument(0), - ]) - } - }, - BorrowRefRepr::Any(value) => match value.type_hash() { - String::HASH => { - let s = vm_try!(value.borrow_ref::()); - this.split_once(s.as_str()) - } _ => { return VmResult::err([ VmErrorKind::expected::(value.type_info()), @@ -986,12 +985,6 @@ fn split_once(this: &str, value: Value) -> VmResult> { ]); } }, - ref actual => { - return VmResult::err([ - VmErrorKind::expected::(actual.type_info()), - VmErrorKind::bad_argument(0), - ]) - } }; let Some((a, b)) = outcome else { diff --git a/crates/rune/src/runtime/function.rs b/crates/rune/src/runtime/function.rs index 252f45b6d..d0a04da56 100644 --- a/crates/rune/src/runtime/function.rs +++ b/crates/rune/src/runtime/function.rs @@ -4,19 +4,21 @@ use core::future::Future; use ::rust_alloc::sync::Arc; use crate as rune; +use crate::alloc::fmt::TryWrite; use crate::alloc::prelude::*; use crate::alloc::{self, Box, Vec}; use crate::function; use crate::runtime::vm::Isolated; -use crate::runtime::{ - Args, Call, ConstValue, FromValue, FunctionHandler, GuardedArgs, InstAddress, Mutable, Output, - OwnedTuple, RefRepr, Rtti, RuntimeContext, RuntimeError, Stack, Unit, Value, VariantRtti, Vm, - VmCall, VmErrorKind, VmHalt, VmResult, -}; use crate::shared::AssertSend; use crate::Any; use crate::Hash; +use super::{ + Args, Call, ConstValue, Formatter, FromValue, FunctionHandler, GuardedArgs, InstAddress, + Mutable, Output, OwnedTuple, RefRepr, Rtti, RuntimeContext, RuntimeError, Stack, Unit, Value, + VariantRtti, Vm, VmCall, VmErrorKind, VmHalt, VmResult, +}; + /// The type of a function in Rune. /// /// Functions can be called using call expression syntax, such as `()`. @@ -44,7 +46,6 @@ use crate::Hash; /// ``` #[derive(Any, TryClone)] #[repr(transparent)] -#[rune(builtin, static_type = FUNCTION)] #[rune(item = ::std::ops)] pub struct Function(FunctionImpl); @@ -364,6 +365,40 @@ impl Function { pub fn into_sync(self) -> Result { Ok(SyncFunction(self.0.into_sync()?)) } + + /// Clone a function. + /// + /// # Examples + /// + /// ```rune + /// fn function() { + /// 42 + /// } + /// + /// let a = function; + /// let b = a.clone(); + /// assert_eq!(a(), b()); + /// ``` + #[rune::function(keep, protocol = CLONE)] + fn clone(&self) -> VmResult { + VmResult::Ok(vm_try!(self.try_clone())) + } + + /// Debug format a function. + /// + /// # Examples + /// + /// ```rune + /// fn function() { + /// 42 + /// } + /// + /// println!("{function:?}"); + /// `` + #[rune::function(keep, protocol = DEBUG_FMT)] + fn debug_fmt(&self, f: &mut Formatter) -> VmResult<()> { + vm_write!(f, "{self:?}") + } } /// A callable sync function. This currently only supports a subset of values @@ -1025,17 +1060,10 @@ struct FnTupleVariant { impl FromValue for SyncFunction { #[inline] fn from_value(value: Value) -> Result { - value.into_function()?.into_sync() + value.into_any::()?.into_sync() } } -from_value2!( - Function, - into_function_ref, - into_function_mut, - into_function -); - fn check_args(actual: usize, expected: usize) -> VmResult<()> { if actual != expected { return VmResult::err(VmErrorKind::BadArgumentCount { expected, actual }); diff --git a/crates/rune/src/runtime/static_type.rs b/crates/rune/src/runtime/static_type.rs index 28330326e..3743e1887 100644 --- a/crates/rune/src/runtime/static_type.rs +++ b/crates/rune/src/runtime/static_type.rs @@ -200,8 +200,6 @@ static_type! { impl for Option; } - pub(crate) static [FUNCTION, FUNCTION_HASH] = ::std::ops::Function {} - pub(crate) static [TYPE, TYPE_HASH] = ::std::any::Type { impl for rt::Type; } diff --git a/crates/rune/src/runtime/value.rs b/crates/rune/src/runtime/value.rs index 91e627f84..eb1635860 100644 --- a/crates/rune/src/runtime/value.rs +++ b/crates/rune/src/runtime/value.rs @@ -32,10 +32,10 @@ use crate::{Any, Hash, TypeHash}; use super::static_type; use super::{ AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, CallResultOnly, ConstValue, - ConstValueKind, DynGuardedArgs, EnvProtocolCaller, Formatter, FromValue, Function, Future, - IntoOutput, Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol, ProtocolCaller, - RawAnyObjGuard, Ref, RuntimeError, Shared, Snapshot, Type, TypeInfo, Variant, Vec, VmErrorKind, - VmIntegerRepr, VmResult, + ConstValueKind, DynGuardedArgs, EnvProtocolCaller, Formatter, FromValue, Future, IntoOutput, + Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol, ProtocolCaller, RawAnyObjGuard, Ref, + RuntimeError, Shared, Snapshot, Type, TypeInfo, Variant, Vec, VmErrorKind, VmIntegerRepr, + VmResult, }; #[cfg(feature = "alloc")] use super::{Hasher, Tuple}; @@ -429,7 +429,6 @@ impl Value { 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())), - Mutable::Function(value) => Mutable::Function(vm_try!(value.try_clone())), _ => { break 'fallback; } @@ -512,9 +511,6 @@ impl Value { Mutable::Variant(value) => { vm_try!(vm_write!(f, "{value:?}")); } - Mutable::Function(value) => { - vm_try!(vm_write!(f, "{value:?}")); - } }; return VmResult::Ok(()); @@ -803,16 +799,6 @@ impl Value { as_result, } - into! { - /// Coerce into a [`Function`]. - Function(Function), - into_function_ref, - into_function_mut, - borrow_function_ref, - borrow_function_mut, - into_function, - } - into! { /// Coerce into [`Struct`] Struct(Struct), @@ -1905,7 +1891,6 @@ inline_from! { } from! { - Function => Function, EmptyStruct => EmptyStruct, TupleStruct => TupleStruct, Struct => Struct, @@ -1924,6 +1909,7 @@ any_from! { super::OwnedTuple, super::Generator, super::Stream, + super::Function, } from_container! { @@ -2063,8 +2049,6 @@ pub(crate) enum Mutable { Struct(Struct), /// The variant of an enum. Variant(Variant), - /// A stored function pointer. - Function(Function), } impl Mutable { @@ -2074,7 +2058,6 @@ impl Mutable { Mutable::Future(..) => TypeInfo::static_type(static_type::FUTURE), Mutable::Option(..) => TypeInfo::static_type(static_type::OPTION), Mutable::Result(..) => TypeInfo::static_type(static_type::RESULT), - Mutable::Function(..) => TypeInfo::static_type(static_type::FUNCTION), Mutable::EmptyStruct(empty) => empty.type_info(), Mutable::TupleStruct(tuple) => tuple.type_info(), Mutable::Struct(object) => object.type_info(), @@ -2092,7 +2075,6 @@ impl Mutable { Mutable::Future(..) => static_type::FUTURE.hash, Mutable::Result(..) => static_type::RESULT.hash, Mutable::Option(..) => static_type::OPTION.hash, - Mutable::Function(..) => static_type::FUNCTION.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/serde.rs b/crates/rune/src/runtime/value/serde.rs index 6c39f32c3..84f022aa2 100644 --- a/crates/rune/src/runtime/value/serde.rs +++ b/crates/rune/src/runtime/value/serde.rs @@ -58,9 +58,6 @@ impl ser::Serialize for Value { Mutable::Variant(..) => Err(ser::Error::custom("cannot serialize variants")), Mutable::Result(..) => Err(ser::Error::custom("cannot serialize results")), Mutable::Future(..) => Err(ser::Error::custom("cannot serialize futures")), - Mutable::Function(..) => { - Err(ser::Error::custom("cannot serialize function pointers")) - } }, BorrowRefRepr::Any(value) => match value.type_hash() { String::HASH => { diff --git a/crates/rune/src/runtime/vm.rs b/crates/rune/src/runtime/vm.rs index eacacaa92..fa55b3710 100644 --- a/crates/rune/src/runtime/vm.rs +++ b/crates/rune/src/runtime/vm.rs @@ -3412,7 +3412,7 @@ impl Vm { #[cfg_attr(feature = "bench", inline(never))] fn op_load_fn(&mut self, hash: Hash, out: Output) -> VmResult<()> { let function = vm_try!(self.lookup_function_by_hash(hash)); - vm_try!(out.store(&mut self.stack, Mutable::Function(function))); + vm_try!(out.store(&mut self.stack, function)); VmResult::Ok(()) } @@ -3464,7 +3464,7 @@ impl Vm { hash, ); - vm_try!(out.store(&mut self.stack, Mutable::Function(function))); + vm_try!(out.store(&mut self.stack, function)); VmResult::Ok(()) } @@ -3629,19 +3629,18 @@ impl Vm { return VmResult::Ok(None); } - let function = function.clone(); - let function = vm_try!(function.borrow_ref_repr()); - - match function { - BorrowRefRepr::Mutable(value) => match &*value { - Mutable::Function(function) => function.call_with_vm(self, addr, args, out), - actual => err(VmErrorKind::UnsupportedCallFn { - actual: actual.type_info(), - }), - }, - actual => err(VmErrorKind::UnsupportedCallFn { - actual: actual.type_info(), + match vm_try!(function.as_ref_repr()) { + RefRepr::Inline(value) => err(VmErrorKind::UnsupportedCallFn { + actual: value.type_info(), + }), + RefRepr::Mutable(value) => err(VmErrorKind::UnsupportedCallFn { + actual: vm_try!(value.borrow_ref()).type_info(), }), + RefRepr::Any(value) => { + let value = value.clone(); + let f = vm_try!(value.borrow_ref::()); + f.call_with_vm(self, addr, args, out) + } } }