prelude!();
use std::cell::Cell;
use std::rc::Rc;
use crate::compile::meta;
use crate::runtime::{AnyTypeInfo, RuntimeError};
#[test]
fn bug_344_function() -> Result<()> {
let mut context = Context::new();
let mut module = Module::new();
module.function("function", function).build()?;
context.install(module)?;
let runtime = context.runtime()?;
let function = runtime.function(&hash!(function)).expect("expect function");
let mut stack = Stack::new();
stack.push(rune::to_value(GuardCheck::new())?)?;
function(&mut stack, InstAddress::new(0), 1, Output::keep(0)).into_result()?;
assert_eq!(stack.at(InstAddress::new(0)).as_signed()?, 42);
return Ok(());
fn function(check: &GuardCheck) -> i64 {
check.ensure_not_dropped("immediate argument");
42
}
}
#[test]
fn bug_344_inst_fn() -> Result<()> {
#[rune::function(instance)]
fn function(s: &GuardCheck, check: &GuardCheck) -> i64 {
s.ensure_not_dropped("async self argument");
check.ensure_not_dropped("async instance argument");
42
}
let mut context = Context::new();
let mut module = Module::new();
module.ty::<GuardCheck>()?;
module.function_meta(function)?;
context.install(module)?;
let runtime = context.runtime()?;
let hash = Hash::associated_function(GuardCheck::HASH, "function");
let function = runtime.function(&hash).expect("expect function");
let mut stack = Stack::new();
stack.push(rune::to_value(GuardCheck::new())?)?;
stack.push(rune::to_value(GuardCheck::new())?)?;
function(&mut stack, InstAddress::ZERO, 2, Output::keep(0)).into_result()?;
assert_eq!(stack.at(InstAddress::ZERO).as_signed()?, 42);
Ok(())
}
#[test]
fn bug_344_async_function() -> Result<()> {
let mut context = Context::new();
let mut module = Module::new();
module.function("function", function).build()?;
context.install(module)?;
let runtime = context.runtime()?;
let function = runtime.function(&hash!(function)).expect("expect function");
let mut stack = Stack::new();
stack.push(rune::to_value(GuardCheck::new())?)?;
function(&mut stack, InstAddress::ZERO, 1, Output::keep(0)).into_result()?;
let future = stack.at(InstAddress::ZERO).clone().into_future()?;
assert_eq!(block_on(future).into_result()?.as_signed()?, 42);
return Ok(());
async fn function(check: Ref<GuardCheck>) -> i64 {
check.ensure_not_dropped("async argument");
42
}
}
#[test]
fn bug_344_async_inst_fn() -> Result<()> {
#[rune::function(instance)]
async fn function(s: Ref<GuardCheck>, check: Ref<GuardCheck>) -> VmResult<i64> {
s.ensure_not_dropped("self argument");
check.ensure_not_dropped("instance argument");
VmResult::Ok(42)
}
let mut context = Context::new();
let mut module = Module::new();
module.ty::<GuardCheck>()?;
module.function_meta(function)?;
context.install(module)?;
let runtime = context.runtime()?;
let hash = Hash::associated_function(GuardCheck::HASH, "function");
let function = runtime.function(&hash).expect("expect function");
let mut stack = Stack::new();
stack.push(rune::to_value(GuardCheck::new())?)?;
stack.push(rune::to_value(GuardCheck::new())?)?;
function(&mut stack, InstAddress::new(0), 2, Output::keep(0)).into_result()?;
let future = stack.at(InstAddress::new(0)).clone().into_future()?;
assert_eq!(block_on(future).into_result()?.as_signed()?, 42);
Ok(())
}
struct Guard {
#[allow(unused)]
guard: RawAnyGuard,
dropped: Rc<Cell<bool>>,
}
impl Drop for Guard {
fn drop(&mut self) {
self.dropped.set(true);
}
}
struct GuardCheck {
dropped: Rc<Cell<bool>>,
}
impl GuardCheck {
fn new() -> Self {
Self {
dropped: Rc::new(Cell::new(false)),
}
}
fn ensure_not_dropped(&self, what: &str) {
assert!(
!self.dropped.get(),
"value has was previously dropped: {}",
what
);
}
}
impl Any for GuardCheck {}
impl rune::__private::AnyMarker for GuardCheck {}
impl Named for GuardCheck {
const ITEM: &'static Item = rune_macros::item!(GuardCheck);
}
impl TypeHash for GuardCheck {
const HASH: Hash = rune_macros::hash!(GuardCheck);
}
impl TypeOf for GuardCheck {
const STATIC_TYPE_INFO: AnyTypeInfo = GuardCheck::ANY_TYPE_INFO;
}
impl MaybeTypeOf for GuardCheck {
#[inline]
fn maybe_type_of() -> alloc::Result<meta::DocType> {
Ok(meta::DocType::new(Self::HASH))
}
}
impl InstallWith for GuardCheck {}
impl UnsafeToRef for GuardCheck {
type Guard = Guard;
#[inline]
unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError> {
let (output, guard) = Ref::into_raw(value.into_ref::<GuardCheck>()?);
let guard = Guard {
guard,
dropped: output.as_ref().dropped.clone(),
};
Ok((output.as_ref(), guard))
}
}