diff --git a/book/listings/ch01-getting-started/listing04.rs b/book/listings/ch01-getting-started/listing04.rs index 489ae575e..e7984d16b 100644 --- a/book/listings/ch01-getting-started/listing04.rs +++ b/book/listings/ch01-getting-started/listing04.rs @@ -1,20 +1,17 @@ -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; use std::{cell::RefCell, env, rc::Rc}; fn main() { let lib_path = env::args().nth(1).expect("Expected path to a Mun library."); - let mut runtime = RuntimeBuilder::new(lib_path) - .spawn() + let mut runtime = Runtime::builder(lib_path) + .finish() .expect("Failed to spawn Runtime"); loop { - { - let runtime_ref = runtime.borrow(); - let arg: i64 = runtime_ref.invoke("arg", ()).unwrap(); - let result: i64 = runtime_ref.invoke("fibonacci", (arg,)).unwrap(); - println!("fibonacci({}) = {}", arg, result); - } - runtime.borrow_mut().update(); + let arg: i64 = runtime.invoke("arg", ()).unwrap(); + let result: i64 = runtime.invoke("fibonacci", (arg,)).unwrap(); + println!("fibonacci({}) = {}", arg, result); + runtime.update(); } } diff --git a/book/listings/ch02-basic-concepts/listing02.rs b/book/listings/ch02-basic-concepts/listing02.rs index d72ff69cc..47b04cc18 100644 --- a/book/listings/ch02-basic-concepts/listing02.rs +++ b/book/listings/ch02-basic-concepts/listing02.rs @@ -1,12 +1,11 @@ -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; use std::{cell::RefCell, rc::Rc}; fn main() { - let runtime = RuntimeBuilder::new("main.munlib") - .spawn() + let runtime = Runtime::builder("main.munlib") + .finish() .expect("Failed to spawn Runtime"); - let runtime_ref = runtime.borrow(); - let result: bool = runtime_ref.invoke("random_bool", ()).unwrap(); + let result: bool = runtime.invoke("random_bool", ()).unwrap(); println!("random bool: {}", result); } diff --git a/book/listings/ch02-basic-concepts/listing03.rs b/book/listings/ch02-basic-concepts/listing03.rs index c1a8967a7..1264c2473 100644 --- a/book/listings/ch02-basic-concepts/listing03.rs +++ b/book/listings/ch02-basic-concepts/listing03.rs @@ -1,4 +1,4 @@ -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; use std::{cell::RefCell, rc::Rc}; extern "C" fn random() -> i64 { @@ -8,12 +8,11 @@ extern "C" fn random() -> i64 { } fn main() { - let runtime = RuntimeBuilder::new("main.munlib") + let runtime = Runtime::builder("main.munlib") .insert_fn("random", random as extern "C" fn() -> i64) - .spawn() + .finish() .expect("Failed to spawn Runtime"); - let runtime_ref = runtime.borrow(); - let result: bool = runtime_ref.invoke("random_bool", ()).unwrap(); + let result: bool = runtime.invoke("random_bool", ()).unwrap(); println!("random_bool: {}", result); } diff --git a/book/listings/ch03-structs/listing11.rs b/book/listings/ch03-structs/listing11.rs index 874d69507..fb95b194f 100644 --- a/book/listings/ch03-structs/listing11.rs +++ b/book/listings/ch03-structs/listing11.rs @@ -1,16 +1,15 @@ # extern crate mun_runtime; -use mun_runtime::{RuntimeBuilder, StructRef}; +use mun_runtime::{Runtime, StructRef}; use std::{cell::RefCell, env, rc::Rc}; fn main() { let lib_path = env::args().nth(1).expect("Expected path to a Mun library."); - let runtime = RuntimeBuilder::new(lib_path) - .spawn() + let runtime = Runtime::builder(lib_path) + .finish() .expect("Failed to spawn Runtime"); - let runtime_ref = runtime.borrow(); - let a: StructRef = runtime_ref.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap(); - let b: StructRef = runtime_ref.invoke("vector2_new", (1.0f32, -1.0f32)).unwrap(); - let added: StructRef = runtime_ref.invoke("vector2_add", (a, b)).unwrap(); + let a: StructRef = runtime.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap(); + let b: StructRef = runtime.invoke("vector2_new", (1.0f32, -1.0f32)).unwrap(); + let added: StructRef = runtime.invoke("vector2_add", (a, b)).unwrap(); } diff --git a/book/listings/ch03-structs/listing12.rs b/book/listings/ch03-structs/listing12.rs index d88e0f512..51965c345 100644 --- a/book/listings/ch03-structs/listing12.rs +++ b/book/listings/ch03-structs/listing12.rs @@ -1,17 +1,16 @@ # extern crate mun_runtime; -# use mun_runtime::{RuntimeBuilder, StructRef}; +# use mun_runtime::{Runtime, StructRef}; # use std::{cell::RefCell, env, rc::Rc}; # # fn main() { # let lib_path = env::args().nth(1).expect("Expected path to a Mun library."); # -# let mut runtime = -# RuntimeBuilder::new(lib_path) -# .spawn() +# let runtime = +# Runtime::builder(lib_path) +# .finish() # .expect("Failed to spawn Runtime"); # - let runtime_ref = runtime.borrow(); - let mut xy: StructRef = runtime_ref.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap(); + let mut xy: StructRef = runtime.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap(); let x: f32 = xy.get("x").unwrap(); xy.set("x", x * x).unwrap(); let y = xy.replace("y", -1.0f32).unwrap(); diff --git a/book/listings/ch03-structs/listing14.rs b/book/listings/ch03-structs/listing14.rs index cc83a763e..ae4a406b9 100644 --- a/book/listings/ch03-structs/listing14.rs +++ b/book/listings/ch03-structs/listing14.rs @@ -1,5 +1,5 @@ # extern crate mun_runtime; -use mun_runtime::{RuntimeBuilder, StructRef}; +use mun_runtime::{Runtime, StructRef}; use std::{env, time}; extern "C" fn log_f32(value: f32) { @@ -9,16 +9,12 @@ extern "C" fn log_f32(value: f32) { fn main() { let lib_dir = env::args().nth(1).expect("Expected path to a Mun library."); - let runtime = RuntimeBuilder::new(lib_dir) + let runtime = Runtime::builder(lib_dir) .insert_fn("log_f32", log_f32 as extern "C" fn(f32)) - .spawn() + .finish() .expect("Failed to spawn Runtime"); - let ctx = { - let runtime_ref = runtime.borrow(); - let ctx: StructRef = runtime_ref.invoke("new_sim", ()).unwrap(); - ctx.root(runtime.clone()) - }; + let ctx = runtime.invoke::("new_sim", ()).unwrap().root(); let mut previous = time::Instant::now(); const FRAME_TIME: time::Duration = time::Duration::from_millis(40); @@ -33,12 +29,9 @@ fn main() { elapsed.as_secs_f32() }; - { - let runtime_ref = runtime.borrow(); - let _: () = runtime_ref.invoke("sim_update", (unsafe { ctx.as_ref(&runtime_ref) }, elapsed_secs)).unwrap(); - } + let _: () = runtime.invoke("sim_update", (ctx.as_ref(&runtime), elapsed_secs)).unwrap(); previous = now; - runtime.borrow_mut().update(); + runtime.update(); } } diff --git a/crates/mun/src/ops/start.rs b/crates/mun/src/ops/start.rs index 27f86d198..8cd9bf7bd 100644 --- a/crates/mun/src/ops/start.rs +++ b/crates/mun/src/ops/start.rs @@ -1,18 +1,15 @@ -use std::{cell::RefCell, rc::Rc}; - use anyhow::anyhow; use clap::ArgMatches; -use mun_runtime::{ReturnTypeReflection, Runtime, RuntimeBuilder}; +use mun_runtime::{ReturnTypeReflection, Runtime}; use crate::ExitStatus; /// Starts the runtime with the specified library and invokes function `entry`. -pub fn start(matches: &ArgMatches) -> Result { +pub fn start(matches: &ArgMatches) -> anyhow::Result { let runtime = runtime(matches)?; - let borrowed = runtime.borrow(); let entry_point = matches.value_of("entry").unwrap_or("main"); - let fn_definition = borrowed + let fn_definition = runtime .get_function_definition(entry_point) .ok_or_else(|| { std::io::Error::new( @@ -24,19 +21,19 @@ pub fn start(matches: &ArgMatches) -> Result { if let Some(ret_type) = fn_definition.prototype.signature.return_type() { let type_guid = &ret_type.guid; if *type_guid == bool::type_guid() { - let result: bool = borrowed + let result: bool = runtime .invoke(entry_point, ()) .map_err(|e| anyhow!("{}", e))?; println!("{}", result) } else if *type_guid == f64::type_guid() { - let result: f64 = borrowed + let result: f64 = runtime .invoke(entry_point, ()) .map_err(|e| anyhow!("{}", e))?; println!("{}", result) } else if *type_guid == i64::type_guid() { - let result: i64 = borrowed + let result: i64 = runtime .invoke(entry_point, ()) .map_err(|e| anyhow!("{}", e))?; @@ -50,17 +47,16 @@ pub fn start(matches: &ArgMatches) -> Result { Ok(ExitStatus::Success) } else { #[allow(clippy::unit_arg)] - borrowed + runtime .invoke(entry_point, ()) .map(|_: ()| ExitStatus::Success) .map_err(|e| anyhow!("{}", e)) } } -fn runtime(matches: &ArgMatches) -> Result>, anyhow::Error> { - let builder = RuntimeBuilder::new( +fn runtime(matches: &ArgMatches) -> anyhow::Result { + Runtime::builder( matches.value_of("LIBRARY").unwrap(), // Safe because its a required arg - ); - - builder.spawn() + ) + .finish() } diff --git a/crates/mun/tests/integration.rs b/crates/mun/tests/integration.rs index a68138c15..c4d55763d 100644 --- a/crates/mun/tests/integration.rs +++ b/crates/mun/tests/integration.rs @@ -1,5 +1,5 @@ use mun::run_with_args; -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; use std::ffi::OsString; use std::path::Path; @@ -73,8 +73,7 @@ fn build_and_run(project: &Path) { let library_path = project.join("target/mod.munlib"); assert!(library_path.is_file()); - let runtime = RuntimeBuilder::new(&library_path).spawn().unwrap(); - let runtime_ref = runtime.borrow(); - let result: f64 = runtime_ref.invoke("main", ()).unwrap(); + let runtime = Runtime::builder(&library_path).finish().unwrap(); + let result: f64 = runtime.invoke("main", ()).unwrap(); assert_eq!(result, 3.14159); } diff --git a/crates/mun_memory/src/gc/root_ptr.rs b/crates/mun_memory/src/gc/root_ptr.rs index 905c312ec..8874e7652 100644 --- a/crates/mun_memory/src/gc/root_ptr.rs +++ b/crates/mun_memory/src/gc/root_ptr.rs @@ -36,6 +36,11 @@ impl> GcRootPtr { } } + /// Returns the runtime that owns the memory + pub fn runtime(&self) -> &Weak { + &self.runtime + } + /// Returns the handle of this instance pub fn handle(&self) -> GcPtr { self.handle diff --git a/crates/mun_runtime/examples/buoyancy.rs b/crates/mun_runtime/examples/buoyancy.rs index 67980a929..5d5b37537 100644 --- a/crates/mun_runtime/examples/buoyancy.rs +++ b/crates/mun_runtime/examples/buoyancy.rs @@ -1,4 +1,4 @@ -use mun_runtime::{RuntimeBuilder, StructRef}; +use mun_runtime::{Runtime, StructRef}; use std::{env, time}; extern "C" fn log_f32(value: f32) { @@ -12,13 +12,15 @@ extern "C" fn log_f32(value: f32) { fn main() { let lib_dir = env::args().nth(1).expect("Expected path to a Mun library."); - let runtime = RuntimeBuilder::new(lib_dir) + let mut runtime = Runtime::builder(lib_dir) .insert_fn("log_f32", log_f32 as extern "C" fn(f32)) - .spawn() + .finish() .expect("Failed to spawn Runtime"); - let runtime_ref = runtime.borrow(); - let ctx: StructRef = runtime_ref.invoke("new_sim", ()).unwrap(); + let ctx = runtime + .invoke::("new_sim", ()) + .unwrap() + .root(); let mut previous = time::Instant::now(); const FRAME_TIME: time::Duration = time::Duration::from_millis(40); @@ -33,12 +35,11 @@ fn main() { elapsed.as_secs_f32() }; - let runtime_ref = runtime.borrow(); - let _: () = runtime_ref - .invoke("sim_update", (ctx.clone(), elapsed_secs)) + let _: () = runtime + .invoke("sim_update", (ctx.as_ref(&runtime), elapsed_secs)) .unwrap(); previous = now; - runtime.borrow_mut().update(); + runtime.update(); } } diff --git a/crates/mun_runtime/examples/fibonacci.rs b/crates/mun_runtime/examples/fibonacci.rs index 03a0d30f7..fddbc7312 100644 --- a/crates/mun_runtime/examples/fibonacci.rs +++ b/crates/mun_runtime/examples/fibonacci.rs @@ -1,4 +1,4 @@ -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; use std::env; // How to run? @@ -9,20 +9,18 @@ fn main() { let lib_dir = env::args().nth(1).expect("Expected path to a Mun library."); println!("lib: {}", lib_dir); - let runtime = RuntimeBuilder::new(lib_dir) - .spawn() + let mut runtime = Runtime::builder(lib_dir) + .finish() .expect("Failed to spawn Runtime"); - let mut runtime_ref = runtime.borrow_mut(); - loop { - let n: i64 = runtime_ref + let n: i64 = runtime .invoke("nth", ()) - .unwrap_or_else(|e| e.wait(&mut runtime_ref)); - let result: i64 = runtime_ref + .unwrap_or_else(|e| e.wait(&mut runtime)); + let result: i64 = runtime .invoke("fibonacci", (n,)) - .unwrap_or_else(|e| e.wait(&mut runtime_ref)); + .unwrap_or_else(|e| e.wait(&mut runtime)); println!("fibonacci({}) = {}", n, result); - runtime_ref.update(); + runtime.update(); } } diff --git a/crates/mun_runtime/src/adt.rs b/crates/mun_runtime/src/adt.rs index a6cbd562c..00bdcdc45 100644 --- a/crates/mun_runtime/src/adt.rs +++ b/crates/mun_runtime/src/adt.rs @@ -4,17 +4,12 @@ use crate::{ reflection::{ equals_argument_type, equals_return_type, ArgumentReflection, ReturnTypeReflection, }, - Runtime, + GarbageCollector, Runtime, }; use memory::gc::{GcRuntime, HasIndirectionPtr}; use once_cell::sync::OnceCell; -use std::cell::{Ref, RefCell}; use std::{ - marker::PhantomPinned, - mem::MaybeUninit, - pin::Pin, ptr::{self, NonNull}, - rc::Rc, sync::Arc, }; @@ -53,8 +48,8 @@ impl<'s> StructRef<'s> { } /// Roots the `StructRef`. - pub fn root(self, runtime: Rc>) -> RootedStruct { - RootedStruct::new(&self.runtime.gc, runtime, self.raw) + pub fn root(self) -> RootedStruct { + RootedStruct::new(&self.runtime.gc, self.raw) } /// Returns the type information of the struct. @@ -291,87 +286,23 @@ impl<'s> Marshal<'s> for StructRef<'s> { #[derive(Clone)] pub struct RootedStruct { handle: GcRootPtr, - runtime: Rc>, } impl RootedStruct { /// Creates a `RootedStruct` that wraps a raw Mun struct. - fn new>( - gc: &Arc, - runtime: Rc>, - raw: RawStruct, - ) -> Self { - let handle = { - let runtime_ref = runtime.borrow(); - // Safety: The type returned from `ptr_type` is guaranteed to live at least as long as - // `Runtime` does not change. As we hold a shared reference to `Runtime`, this is safe. - assert!(unsafe { gc.ptr_type(raw.0).into_inner().as_ref().data.is_struct() }); - - GcRootPtr::new(&runtime_ref.gc, raw.0) - }; - - Self { handle, runtime } + fn new(gc: &Arc, raw: RawStruct) -> Self { + // Safety: The type returned from `ptr_type` is guaranteed to live at least as long as + // `Runtime` does not change. As we hold a shared reference to `Runtime`, this is safe. + assert!(unsafe { gc.ptr_type(raw.0).into_inner().as_ref().data.is_struct() }); + Self { + handle: GcRootPtr::new(gc, raw.0), + } } /// Converts the `RootedStruct` into a `StructRef`, using an external shared reference to a /// `Runtime`. - /// - /// # Safety - /// - /// The `RootedStruct` should have been allocated by the `Runtime`. - pub unsafe fn as_ref<'r>(&self, runtime: &'r Runtime) -> StructRef<'r> { + pub fn as_ref<'r>(&self, runtime: &'r Runtime) -> StructRef<'r> { + assert_eq!(Arc::as_ptr(&runtime.gc), self.handle.runtime().as_ptr()); StructRef::new(RawStruct(self.handle.handle()), runtime) } - - /// Converts the `RootedStruct` to a pinned `RootedStructRef` that can be used just like a - /// `StructRef`. - pub fn by_ref(&self) -> Pin> { - RootedStructRef::new(RawStruct(self.handle.handle()), self.borrow_runtime()) - } - - /// Borrows the struct's runtime. - pub fn borrow_runtime(&self) -> Ref { - self.runtime.borrow() - } -} - -/// Type-agnostic wrapper for safely obtaining a `StructRef` from a `RootedStruct`. -pub struct RootedStructRef<'s> { - runtime: Ref<'s, Runtime>, - struct_ref: MaybeUninit>, - _pin: PhantomPinned, -} - -impl<'s> RootedStructRef<'s> { - fn new(raw: RawStruct, runtime: Ref<'s, Runtime>) -> Pin> { - let struct_ref = RootedStructRef { - runtime, - struct_ref: MaybeUninit::uninit(), - _pin: PhantomPinned, - }; - let mut boxed = Box::pin(struct_ref); - - let runtime = NonNull::from(&boxed.runtime); - - // Safety: Modifying a field doesn't move the whole struct - unsafe { - let struct_ref = StructRef::new(raw, &*runtime.as_ptr()); - let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); - Pin::get_unchecked_mut(mut_ref) - .struct_ref - .as_mut_ptr() - .write(struct_ref); - } - - boxed - } -} - -impl<'s> std::ops::Deref for RootedStructRef<'s> { - type Target = StructRef<'s>; - - fn deref(&self) -> &Self::Target { - // Safety: We always guarantee to set the `struct_ref` upon construction. - unsafe { &*self.struct_ref.as_ptr() } - } } diff --git a/crates/mun_runtime/src/lib.rs b/crates/mun_runtime/src/lib.rs index 12d1b956a..9f39e6f8a 100644 --- a/crates/mun_runtime/src/lib.rs +++ b/crates/mun_runtime/src/lib.rs @@ -19,12 +19,10 @@ use mun_project::LOCKFILE_NAME; use notify::{RawEvent, RecommendedWatcher, RecursiveMode, Watcher}; use rustc_hash::FxHashMap; use std::{ - cell::RefCell, collections::{HashMap, VecDeque}, ffi, io, mem, path::{Path, PathBuf}, ptr::NonNull, - rc::Rc, string::ToString, sync::{ mpsc::{channel, Receiver}, @@ -87,7 +85,7 @@ pub struct RuntimeBuilder { impl RuntimeBuilder { /// Constructs a new `RuntimeBuilder` for the shared library at `library_path`. - pub fn new>(library_path: P) -> Self { + fn new>(library_path: P) -> Self { Self { options: RuntimeOptions { library_path: library_path.into(), @@ -106,9 +104,9 @@ impl RuntimeBuilder { self } - /// Spawns a [`Runtime`] with the builder's options. - pub fn spawn(self) -> anyhow::Result>> { - Runtime::new(self.options).map(|runtime| Rc::new(RefCell::new(runtime))) + /// Constructs a [`Runtime`] with the builder's options. + pub fn finish(self) -> anyhow::Result { + Runtime::new(self.options) } } @@ -203,6 +201,11 @@ pub struct Runtime { } impl Runtime { + /// Constructs a new [`RuntimeBuilder`] to construct a new [`Runtime`] instance. + pub fn builder>(library_path: P) -> RuntimeBuilder { + RuntimeBuilder::new(library_path) + } + /// Constructs a new `Runtime` that loads the library at `library_path` and its /// dependencies. The `Runtime` contains a file watcher that is triggered with an interval /// of `dur`. @@ -438,25 +441,25 @@ impl Runtime { } /// An error that might occur when calling a mun function from Rust. -pub struct InvokeErr, T> { +pub struct InvokeErr<'name, T> { msg: String, - function_name: Name, + function_name: &'name str, arguments: T, } -impl, T> Debug for InvokeErr { +impl<'name, T> Debug for InvokeErr<'name, T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", &self.msg) } } -impl, T> Display for InvokeErr { +impl<'name, T> Display for InvokeErr<'name, T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", &self.msg) } } -impl, T: InvokeArgs> InvokeErr { +impl<'name, T: InvokeArgs> InvokeErr<'name, T> { /// Retries a function invocation once, resulting in a potentially successful /// invocation. // FIXME: `unwrap_or_else` does not compile for `StructRef`, due to @@ -577,27 +580,24 @@ impl Runtime { pub fn invoke< 'runtime, 'ret, + 'name, ReturnType: ReturnTypeReflection + Marshal<'ret> + 'ret, ArgTypes: InvokeArgs, - Name: AsRef, >( &'runtime self, - function_name: Name, + function_name: &'name str, arguments: ArgTypes, - ) -> Result> + ) -> Result> where 'runtime: 'ret, { // Get the function information from the runtime - let function_name_str = function_name.as_ref(); - let function_info = match self - .get_function_definition(function_name_str) - .ok_or_else(|| { - format!( - "failed to obtain function '{}', no such function exists.", - function_name_str - ) - }) { + let function_info = match self.get_function_definition(function_name).ok_or_else(|| { + format!( + "failed to obtain function '{}', no such function exists.", + function_name + ) + }) { Ok(function_info) => function_info, Err(msg) => { return Err(InvokeErr { diff --git a/crates/mun_runtime/tests/hot_reloading.rs b/crates/mun_runtime/tests/hot_reloading.rs index 82b571df7..78376e985 100644 --- a/crates/mun_runtime/tests/hot_reloading.rs +++ b/crates/mun_runtime/tests/hot_reloading.rs @@ -14,9 +14,7 @@ fn hotreloadable() { .expect("Failed to build test driver"); assert_invoke_eq!(i32, 5, driver, "main"); - let runtime = driver.runtime(); driver.update( - runtime.borrow(), "mod.mun", r" pub fn main() -> i32 { 10 } @@ -46,9 +44,7 @@ fn hotreload_struct_decl() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); driver.update( - runtime.borrow(), "mod.mun", r#" pub struct(gc) Args { diff --git a/crates/mun_runtime/tests/marshalling.rs b/crates/mun_runtime/tests/marshalling.rs index f2a78f61a..573ce24fd 100644 --- a/crates/mun_runtime/tests/marshalling.rs +++ b/crates/mun_runtime/tests/marshalling.rs @@ -256,9 +256,7 @@ fn compiler_valid_utf8() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let foo_func = runtime_ref.get_function_definition("foo").unwrap(); + let foo_func = driver.runtime.get_function_definition("foo").unwrap(); assert_eq!( unsafe { CStr::from_ptr(foo_func.prototype.name) } .to_str() @@ -389,20 +387,19 @@ fn marshal_struct() { assert_eq!(Ok(data.0), s.get::(field_name)); } - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let int_data = TestData(3i32, 6i32); let bool_data = TestData(true, false); // Verify that struct marshalling works for fundamental types - let mut foo: StructRef = runtime_ref + let mut foo: StructRef = driver + .runtime .invoke("foo_new", (int_data.0, bool_data.0)) .unwrap(); test_field(&mut foo, &int_data, "a"); test_field(&mut foo, &bool_data, "b"); - let mut bar: StructRef = runtime_ref + let mut bar: StructRef = driver + .runtime .invoke("bar_new", (int_data.0, bool_data.0)) .unwrap(); test_field(&mut bar, &int_data, "0"); @@ -435,37 +432,43 @@ fn marshal_struct() { } // Verify that struct marshalling works for struct types - let mut baz: StructRef = runtime_ref.invoke("baz_new", (foo,)).unwrap(); - let c1: StructRef = runtime_ref + let mut baz: StructRef = driver.runtime.invoke("baz_new", (foo,)).unwrap(); + let c1: StructRef = driver + .runtime .invoke("foo_new", (int_data.0, bool_data.0)) .unwrap(); - let c2: StructRef = runtime_ref + let c2: StructRef = driver + .runtime .invoke("foo_new", (int_data.1, bool_data.1)) .unwrap(); test_struct(&mut baz, c1, c2); - let mut qux: StructRef = runtime_ref.invoke("qux_new", (bar,)).unwrap(); - let c1: StructRef = runtime_ref + let mut qux: StructRef = driver.runtime.invoke("qux_new", (bar,)).unwrap(); + let c1: StructRef = driver + .runtime .invoke("bar_new", (int_data.0, bool_data.0)) .unwrap(); - let c2: StructRef = runtime_ref + let c2: StructRef = driver + .runtime .invoke("bar_new", (int_data.1, bool_data.1)) .unwrap(); test_struct(&mut qux, c1, c2); // Verify the dispatch table works when a marshallable wrapper function exists alongside the // original function. - let mut baz2: StructRef = runtime_ref + let mut baz2: StructRef = driver + .runtime .invoke("baz_new_transitive", (int_data.0, bool_data.0)) .unwrap(); // TODO: Find an ergonomic solution for this: // .unwrap_or_else(|e| e.wait(&mut runtime_ref)); - let runtime_ref = runtime.borrow(); - let c1: StructRef = runtime_ref + let c1: StructRef = driver + .runtime .invoke("foo_new", (int_data.0, bool_data.0)) .unwrap(); - let c2: StructRef = runtime_ref + let c2: StructRef = driver + .runtime .invoke("foo_new", (int_data.1, bool_data.1)) .unwrap(); test_struct(&mut baz2, c1, c2); @@ -541,11 +544,11 @@ fn marshal_struct() { assert!(bar_err.is_err()); // Specify invalid return type - let bar_err: Result = runtime_ref.invoke("baz_new", (foo,)); + let bar_err: Result = driver.runtime.invoke("baz_new", (foo,)); assert!(bar_err.is_err()); // Pass invalid struct type - let bar_err: Result = runtime_ref.invoke("baz_new", (bar,)); + let bar_err: Result = driver.runtime.invoke("baz_new", (bar,)); assert!(bar_err.is_err()); } @@ -670,10 +673,8 @@ fn test_primitive_types() { assert_eq!(Ok(data.0), s.get::(field_name)); } - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - - let mut foo: StructRef = runtime_ref + let mut foo: StructRef = driver + .runtime .invoke( "new_primitives", ( @@ -711,10 +712,7 @@ fn can_add_external_without_return() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - - let _: () = runtime_ref.invoke("main", ()).unwrap(); + let _: () = driver.runtime.invoke("main", ()).unwrap(); } #[test] diff --git a/crates/mun_runtime/tests/memory.rs b/crates/mun_runtime/tests/memory.rs index 8241e22c3..7422afad9 100644 --- a/crates/mun_runtime/tests/memory.rs +++ b/crates/mun_runtime/tests/memory.rs @@ -30,19 +30,17 @@ fn gc_trace() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); + let runtime = &driver.runtime; + let value: StructRef = runtime.invoke("new_foo", ()).unwrap(); + let value = value.root(); - let value: StructRef = runtime_ref.invoke("new_foo", ()).unwrap(); - let value = value.root(driver.runtime()); - - assert_eq!(runtime_ref.gc_collect(), false); - assert!(runtime_ref.gc_stats().allocated_memory > 0); + assert_eq!(runtime.gc_collect(), false); + assert!(runtime.gc_stats().allocated_memory > 0); drop(value); - assert_eq!(runtime_ref.gc_collect(), true); - assert_eq!(runtime_ref.gc_stats().allocated_memory, 0); + assert_eq!(runtime.gc_collect(), true); + assert_eq!(runtime.gc_stats().allocated_memory, 0); } #[test] @@ -62,16 +60,12 @@ fn map_struct_insert_field1() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let b = 5i64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -81,9 +75,11 @@ fn map_struct_insert_field1() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), 0); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + + let runtime = &driver.runtime; + assert_eq!(foo.as_ref(runtime).get::("a").unwrap(), 0); + assert_eq!(foo.as_ref(runtime).get::("b").unwrap(), b); + assert_eq!(foo.as_ref(runtime).get::("c").unwrap(), c); } #[test] @@ -103,16 +99,12 @@ fn map_struct_insert_field2() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -122,9 +114,9 @@ fn map_struct_insert_field2() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("b").unwrap(), 0.0); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), 0.0); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); } #[test] @@ -144,16 +136,12 @@ fn map_struct_insert_field3() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let b = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -163,9 +151,9 @@ fn map_struct_insert_field3() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), 0.0); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), 0.0); } #[test] @@ -186,17 +174,13 @@ fn map_struct_remove_field1() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 1.0f64; let b = 3.0f64; let c = 5i64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -204,7 +188,7 @@ fn map_struct_remove_field1() { } "#, ); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); } #[test] @@ -225,17 +209,13 @@ fn map_struct_remove_field2() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 1.0f64; let b = 5i64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -243,7 +223,7 @@ fn map_struct_remove_field2() { } "#, ); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); } #[test] @@ -264,17 +244,13 @@ fn map_struct_remove_field3() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let b = 1.0f64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -282,7 +258,7 @@ fn map_struct_remove_field3() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); } #[test] @@ -305,19 +281,15 @@ fn map_struct_cast_fields1() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 1u8; let b = -2i16; let c = 3u32; let d = -4i64; let e = 3.14f32; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c, d, e)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c, d, e)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo( @@ -329,11 +301,26 @@ fn map_struct_cast_fields1() { ) "#, ); - assert_eq!(foo.by_ref().get::("0").unwrap(), a.into()); - assert_eq!(foo.by_ref().get::("1").unwrap(), b.into()); - assert_eq!(foo.by_ref().get::("2").unwrap(), c.into()); - assert_eq!(foo.by_ref().get::("3").unwrap(), d.into()); - assert_eq!(foo.by_ref().get::("4").unwrap(), e.into()); + assert_eq!( + foo.as_ref(&driver.runtime).get::("0").unwrap(), + a.into() + ); + assert_eq!( + foo.as_ref(&driver.runtime).get::("1").unwrap(), + b.into() + ); + assert_eq!( + foo.as_ref(&driver.runtime).get::("2").unwrap(), + c.into() + ); + assert_eq!( + foo.as_ref(&driver.runtime).get::("3").unwrap(), + d.into() + ); + assert_eq!( + foo.as_ref(&driver.runtime).get::("4").unwrap(), + e.into() + ); } #[test] @@ -352,15 +339,11 @@ fn map_struct_cast_fields2() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = -2i16; - let foo: StructRef = runtime_ref.invoke("foo_new", (a,)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a,)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo( @@ -369,7 +352,7 @@ fn map_struct_cast_fields2() { "#, ); - assert_eq!(foo.by_ref().get::("0").unwrap(), 0); + assert_eq!(foo.as_ref(&driver.runtime).get::("0").unwrap(), 0); } #[test] @@ -390,17 +373,13 @@ fn map_struct_swap_fields1() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 1.0f64; let b = 3i64; let c = 5.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -410,9 +389,9 @@ fn map_struct_swap_fields1() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); } #[test] @@ -434,18 +413,14 @@ fn map_struct_swap_fields2() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 1.0f64; let b = 3i64; let c = 5.0f64; let d = 7i64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c, d)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c, d)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -456,10 +431,10 @@ fn map_struct_swap_fields2() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); - assert_eq!(foo.by_ref().get::("d").unwrap(), d); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("d").unwrap(), d); } #[test] @@ -480,17 +455,13 @@ fn map_struct_rename_field1() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let b = 1.0f64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -500,9 +471,9 @@ fn map_struct_rename_field1() { } "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("d").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("d").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); } #[test] @@ -523,17 +494,13 @@ fn map_struct_rename_field2() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let b = 1.0f64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Foo { @@ -543,9 +510,9 @@ fn map_struct_rename_field2() { } "#, ); - assert_eq!(foo.by_ref().get::("d").unwrap(), a); - assert_eq!(foo.by_ref().get::("e").unwrap(), b); - assert_eq!(foo.by_ref().get::("f").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("d").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("e").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("f").unwrap(), c); } #[test] @@ -567,18 +534,14 @@ fn map_struct_all() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i32; let b = 1.0f64; let c = 3.0f64; let d = -1i32; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c, d)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c, d)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" pub struct Foo { @@ -590,10 +553,13 @@ fn map_struct_all() { } "#, ); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("d").unwrap(), d.into()); - assert_eq!(foo.by_ref().get::("e").unwrap(), a); - assert_eq!(foo.by_ref().get::("f").unwrap(), 0); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); + assert_eq!( + foo.as_ref(&driver.runtime).get::("d").unwrap(), + d.into() + ); + assert_eq!(foo.as_ref(&driver.runtime).get::("e").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("f").unwrap(), 0); } #[test] @@ -614,17 +580,13 @@ fn delete_used_struct() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let b = 1.0f64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, b, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, b, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" pub struct Bar(i64); @@ -635,19 +597,11 @@ fn delete_used_struct() { "#, ); - assert!(driver - .runtime() - .borrow() - .get_function_definition("foo_new") - .is_none()); - assert!(driver - .runtime() - .borrow() - .get_function_definition("bar_new") - .is_some()); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("b").unwrap(), b); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert!(driver.runtime.get_function_definition("foo_new").is_none()); + assert!(driver.runtime.get_function_definition("bar_new").is_some()); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("b").unwrap(), b); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); } #[test] @@ -680,31 +634,29 @@ fn nested_structs() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = -3.14f32; let b = 6.18f32; - let gc_struct: StructRef = runtime_ref.invoke("new_gc_struct", (a, b)).unwrap(); - let value_struct: StructRef = runtime_ref.invoke("new_value_struct", (a, b)).unwrap(); + let gc_struct: StructRef = driver.runtime.invoke("new_gc_struct", (a, b)).unwrap(); + let value_struct: StructRef = driver.runtime.invoke("new_value_struct", (a, b)).unwrap(); - let gc_wrapper: StructRef = runtime_ref + let gc_wrapper: StructRef = driver + .runtime .invoke("new_gc_wrapper", (gc_struct.clone(), value_struct.clone())) .unwrap(); - let value_wrapper: StructRef = runtime_ref + let value_wrapper: StructRef = driver + .runtime .invoke( "new_value_wrapper", (gc_struct.clone(), value_struct.clone()), ) .unwrap(); - let gc_wrapper = gc_wrapper.root(driver.runtime()); - let value_wrapper = value_wrapper.root(driver.runtime()); + let gc_wrapper = gc_wrapper.root(); + let value_wrapper = value_wrapper.root(); // Tests mapping of `gc -> gc`, `value -> value` driver.update( - runtime_ref, "mod.mun", r#" pub struct(gc) GcStruct(f64, f64); @@ -715,25 +667,36 @@ fn nested_structs() { "#, ); - let gc_0 = gc_wrapper.by_ref().get::("0").unwrap(); + let gc_0 = gc_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(gc_0.get::("0"), Ok(a.into())); assert_eq!(gc_0.get::("1"), Ok(b.into())); - let gc_1 = gc_wrapper.by_ref().get::("1").unwrap(); + let gc_1 = gc_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(gc_1.get::("0"), Ok(a.into())); assert_eq!(gc_1.get::("1"), Ok(b.into())); - let value_0 = value_wrapper.by_ref().get::("0").unwrap(); + let value_0 = value_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(value_0.get::("0"), Ok(a.into())); assert_eq!(value_0.get::("1"), Ok(b.into())); - let value_1 = value_wrapper.by_ref().get::("1").unwrap(); + let value_1 = value_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(value_1.get::("0"), Ok(a.into())); assert_eq!(value_1.get::("1"), Ok(b.into())); // Tests an identity mapping driver.update( - runtime.borrow(), "mod.mun", r#" pub struct(gc) GcStruct(f64, f64); @@ -744,30 +707,41 @@ fn nested_structs() { "#, ); - let gc_0 = gc_wrapper.by_ref().get::("0").unwrap(); + let gc_0 = gc_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(gc_0.get::("0"), Ok(a.into())); assert_eq!(gc_0.get::("1"), Ok(b.into())); - let gc_1 = gc_wrapper.by_ref().get::("1").unwrap(); + let gc_1 = gc_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(gc_1.get::("0"), Ok(a.into())); assert_eq!(gc_1.get::("1"), Ok(b.into())); - let value_0 = value_wrapper.by_ref().get::("0").unwrap(); + let value_0 = value_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(value_0.get::("0"), Ok(a.into())); assert_eq!(value_0.get::("1"), Ok(b.into())); - let value_1 = value_wrapper.by_ref().get::("1").unwrap(); + let value_1 = value_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(value_1.get::("0"), Ok(a.into())); assert_eq!(value_1.get::("1"), Ok(b.into())); - let gc_0 = gc_0.root(driver.runtime()); - let gc_1 = gc_1.root(driver.runtime()); - let value_0 = value_0.root(driver.runtime()); - let value_1 = value_1.root(driver.runtime()); + let gc_0 = gc_0.root(); + let gc_1 = gc_1.root(); + let value_0 = value_0.root(); + let value_1 = value_1.root(); // Tests mapping of `gc -> value`, `value -> gc` driver.update( - runtime.borrow(), "mod.mun", r#" struct(value) GcStruct(f64, f64); @@ -778,22 +752,33 @@ fn nested_structs() { "#, ); - assert_eq!(gc_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(gc_0.by_ref().get::("1"), Ok(b.into())); + assert_eq!(gc_0.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!(gc_0.as_ref(&driver.runtime).get::("1"), Ok(b.into())); - assert_eq!(gc_1.by_ref().get::("0"), Ok(a.into())); - assert_eq!(gc_1.by_ref().get::("1"), Ok(b.into())); + assert_eq!(gc_1.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!(gc_1.as_ref(&driver.runtime).get::("1"), Ok(b.into())); - assert_eq!(value_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_0.by_ref().get::("1"), Ok(b.into())); + assert_eq!( + value_0.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); + assert_eq!( + value_0.as_ref(&driver.runtime).get::("1"), + Ok(b.into()) + ); - assert_eq!(value_1.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_1.by_ref().get::("1"), Ok(b.into())); + assert_eq!( + value_1.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); + assert_eq!( + value_1.as_ref(&driver.runtime).get::("1"), + Ok(b.into()) + ); // Tests mapping of different struct type, when `gc -> value`, `value -> gc`, and // retention of an old library (due to removal of `GcStruct` and `ValueStruct`) driver.update( - runtime.borrow(), "mod.mun", r#" struct(gc) GcStruct2(f64); @@ -805,43 +790,66 @@ fn nested_structs() { ); // Existing, rooted objects should remain untouched - assert_eq!(gc_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(gc_0.by_ref().get::("1"), Ok(b.into())); + assert_eq!(gc_0.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!(gc_0.as_ref(&driver.runtime).get::("1"), Ok(b.into())); - assert_eq!(gc_1.by_ref().get::("0"), Ok(a.into())); - assert_eq!(gc_1.by_ref().get::("1"), Ok(b.into())); + assert_eq!(gc_1.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!(gc_1.as_ref(&driver.runtime).get::("1"), Ok(b.into())); - assert_eq!(value_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_0.by_ref().get::("1"), Ok(b.into())); + assert_eq!( + value_0.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); + assert_eq!( + value_0.as_ref(&driver.runtime).get::("1"), + Ok(b.into()) + ); - assert_eq!(value_1.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_1.by_ref().get::("1"), Ok(b.into())); + assert_eq!( + value_1.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); + assert_eq!( + value_1.as_ref(&driver.runtime).get::("1"), + Ok(b.into()) + ); // The values in the wrappers should have been updated - let mut gc_0 = gc_wrapper.by_ref().get::("0").unwrap(); + let mut gc_0 = gc_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(gc_0.get::("0"), Ok(0.0)); gc_0.set::("0", a.into()).unwrap(); - let mut gc_1 = gc_wrapper.by_ref().get::("1").unwrap(); + let mut gc_1 = gc_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(gc_1.get::("0"), Ok(0.0)); gc_1.set::("0", a.into()).unwrap(); - let mut value_0 = value_wrapper.by_ref().get::("0").unwrap(); + let mut value_0 = value_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(value_0.get::("0"), Ok(0.0)); value_0.set::("0", a.into()).unwrap(); - let mut value_1 = value_wrapper.by_ref().get::("1").unwrap(); + let mut value_1 = value_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(value_1.get::("0"), Ok(0.0)); value_1.set::("0", a.into()).unwrap(); - let gc_0 = gc_0.root(driver.runtime()); - let gc_1 = gc_1.root(driver.runtime()); - let value_0 = value_0.root(driver.runtime()); - let value_1 = value_1.root(driver.runtime()); + let gc_0 = gc_0.root(); + let gc_1 = gc_1.root(); + let value_0 = value_0.root(); + let value_1 = value_1.root(); // Tests mapping of different struct type, when `gc -> gc`, `value -> value` driver.update( - runtime.borrow(), "mod.mun", r#" struct(gc) GcStruct(f64, f64); @@ -853,25 +861,43 @@ fn nested_structs() { ); // Existing, rooted objects should remain untouched - assert_eq!(gc_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(gc_1.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_0.by_ref().get::("0"), Ok(a.into())); - assert_eq!(value_1.by_ref().get::("0"), Ok(a.into())); + assert_eq!(gc_0.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!(gc_1.as_ref(&driver.runtime).get::("0"), Ok(a.into())); + assert_eq!( + value_0.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); + assert_eq!( + value_1.as_ref(&driver.runtime).get::("0"), + Ok(a.into()) + ); // The values in the wrappers should have been updated - let gc_0 = gc_wrapper.by_ref().get::("0").unwrap(); + let gc_0 = gc_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(gc_0.get::("0"), Ok(0.0)); assert_eq!(gc_0.get::("1"), Ok(0.0)); - let gc_1 = gc_wrapper.by_ref().get::("1").unwrap(); + let gc_1 = gc_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(gc_1.get::("0"), Ok(0.0)); assert_eq!(gc_1.get::("1"), Ok(0.0)); - let value_0 = value_wrapper.by_ref().get::("0").unwrap(); + let value_0 = value_wrapper + .as_ref(&driver.runtime) + .get::("0") + .unwrap(); assert_eq!(value_0.get::("0"), Ok(0.0)); assert_eq!(value_0.get::("1"), Ok(0.0)); - let value_1 = value_wrapper.by_ref().get::("1").unwrap(); + let value_1 = value_wrapper + .as_ref(&driver.runtime) + .get::("1") + .unwrap(); assert_eq!(value_1.get::("0"), Ok(0.0)); assert_eq!(value_1.get::("1"), Ok(0.0)); } @@ -893,16 +919,12 @@ fn insert_struct() { ) .expect("Failed to build test driver"); - let runtime = driver.runtime(); - let runtime_ref = runtime.borrow(); - let a = 5i64; let c = 3.0f64; - let foo: StructRef = runtime_ref.invoke("foo_new", (a, c)).unwrap(); - let foo = foo.root(driver.runtime()); + let foo: StructRef = driver.runtime.invoke("foo_new", (a, c)).unwrap(); + let foo = foo.root(); driver.update( - runtime_ref, "mod.mun", r#" struct Bar(i64); @@ -917,12 +939,12 @@ fn insert_struct() { "#, ); - assert_eq!(foo.by_ref().get::("a").unwrap(), a); - assert_eq!(foo.by_ref().get::("c").unwrap(), c); + assert_eq!(foo.as_ref(&driver.runtime).get::("a").unwrap(), a); + assert_eq!(foo.as_ref(&driver.runtime).get::("c").unwrap(), c); - let b = foo.by_ref().get::("b").unwrap(); + let b = foo.as_ref(&driver.runtime).get::("b").unwrap(); assert_eq!(b.get::("0"), Ok(0)); - let d = foo.by_ref().get::("d").unwrap(); + let d = foo.as_ref(&driver.runtime).get::("d").unwrap(); assert_eq!(d.get::("0"), Ok(0.0)); } diff --git a/crates/mun_runtime/tests/runtime.rs b/crates/mun_runtime/tests/runtime.rs index 57b3a39ca..861caf075 100644 --- a/crates/mun_runtime/tests/runtime.rs +++ b/crates/mun_runtime/tests/runtime.rs @@ -14,11 +14,7 @@ fn invoke() { ) .expect("Failed to build test driver"); - let result: i32 = driver - .runtime() - .borrow() - .invoke("sum", (123i32, 456i32)) - .unwrap(); + let result: i32 = driver.runtime.invoke("sum", (123i32, 456i32)).unwrap(); assert_eq!(123 + 456, result); } diff --git a/crates/mun_runtime/tests/threading.rs b/crates/mun_runtime/tests/threading.rs new file mode 100644 index 000000000..4f71fed4e --- /dev/null +++ b/crates/mun_runtime/tests/threading.rs @@ -0,0 +1,5 @@ +use mun_runtime::Runtime; + +// Ensures the [`Runtime`] is Send +trait IsSend: Send {} +impl IsSend for Runtime {} diff --git a/crates/mun_runtime/tests/util.rs b/crates/mun_runtime/tests/util.rs index f5d720df8..13fb0eab1 100644 --- a/crates/mun_runtime/tests/util.rs +++ b/crates/mun_runtime/tests/util.rs @@ -3,9 +3,7 @@ macro_rules! assert_invoke_eq { ($ExpectedType:ty, $ExpectedResult:expr, $Driver:expr, $Name:expr, $($Arg:expr),*) => { { - let runtime = $Driver.runtime(); - let runtime_ref = runtime.borrow(); - let result: $ExpectedType = runtime_ref.invoke($Name, ( $($Arg,)*) ).unwrap(); + let result: $ExpectedType = $Driver.runtime.invoke($Name, ( $($Arg,)*) ).unwrap(); assert_eq!( result, $ExpectedResult, "{} == {:?}", stringify!(mun_runtime::invoke_fn!(runtime_ref, $($Arg)*).unwrap()), diff --git a/crates/mun_skeptic/src/runtime.rs b/crates/mun_skeptic/src/runtime.rs index 8c99531f2..8953b8955 100644 --- a/crates/mun_skeptic/src/runtime.rs +++ b/crates/mun_skeptic/src/runtime.rs @@ -1,7 +1,7 @@ //! Code to perform tests on Mun code. use mun_compiler::{Config, DisplayColor, PathOrInline, RelativePathBuf}; -use mun_runtime::RuntimeBuilder; +use mun_runtime::Runtime; /// The type of test to create #[derive(Copy, Clone)] @@ -72,18 +72,17 @@ pub fn run_test(code: &str, mode: TestMode) { // Create a runtime let assembly_path = driver.assembly_output_path_from_file(file_id); - let runtime = RuntimeBuilder::new(assembly_path) - .spawn() + let runtime = Runtime::builder(assembly_path) + .finish() .expect("error creating runtime for test assembly"); // Find the main function - if runtime.borrow().get_function_definition("main").is_none() { + if runtime.get_function_definition("main").is_none() { panic!("Could not find `main` function"); } // Call the main function let _: () = runtime - .borrow_mut() .invoke("main", ()) .expect("error calling main function"); } diff --git a/crates/mun_test/src/driver.rs b/crates/mun_test/src/driver.rs index 98bac9d19..ed693d2b1 100644 --- a/crates/mun_test/src/driver.rs +++ b/crates/mun_test/src/driver.rs @@ -1,9 +1,7 @@ use compiler::{Config, DisplayColor, Driver, PathOrInline, RelativePathBuf}; use runtime::{Runtime, RuntimeBuilder}; use std::{ - cell::{Ref, RefCell}, path::{Path, PathBuf}, - rc::Rc, thread::sleep, time::{Duration, Instant}, }; @@ -127,7 +125,9 @@ impl std::fmt::Debug for CompileTestDriver { /// This allows testing of Mun constructs that depend on hot-reloading. pub struct CompileAndRunTestDriver { driver: CompileTestDriver, - runtime: Rc>, + + /// The runtime created by this instance. + pub runtime: Runtime, } impl std::fmt::Debug for CompileAndRunTestDriver { @@ -146,8 +146,8 @@ impl CompileAndRunTestDriver { config_fn: impl FnOnce(RuntimeBuilder) -> RuntimeBuilder, ) -> Result { let driver = CompileTestDriver::from_fixture(fixture); - let builder = RuntimeBuilder::new(driver.lib_path()); - let runtime = config_fn(builder).spawn()?; + let builder = Runtime::builder(driver.lib_path()); + let runtime = config_fn(builder).finish()?; Ok(Self { driver, runtime }) } @@ -159,8 +159,8 @@ impl CompileAndRunTestDriver { config_fn: impl FnOnce(RuntimeBuilder) -> RuntimeBuilder, ) -> Result { let driver = CompileTestDriver::from_file(text); - let builder = RuntimeBuilder::new(driver.lib_path()); - let runtime = config_fn(builder).spawn()?; + let builder = Runtime::builder(driver.lib_path()); + let runtime = config_fn(builder).finish()?; Ok(Self { driver, runtime }) } @@ -171,17 +171,11 @@ impl CompileAndRunTestDriver { /// A reference to the borrowed `runtime` is used as an argument to allow moving of the /// existing borrow inside the update function. This obviates the necessity for `update` to use /// the `Runtime`. - pub fn update( - &mut self, - runtime: Ref<'_, Runtime>, - path: impl AsRef, - text: &str, - ) { + pub fn update(&mut self, path: impl AsRef, text: &str) { self.driver.update(path, text); let start_time = Instant::now(); - drop(runtime); - while !self.runtime().borrow_mut().update() { + while !self.runtime.update() { let now = Instant::now(); if now - start_time > Duration::from_secs(10) { panic!("runtime did not update after recompilation within 10 seconds"); @@ -190,9 +184,4 @@ impl CompileAndRunTestDriver { } } } - - /// Returns the `Runtime` used by the driver. - pub fn runtime(&self) -> Rc> { - self.runtime.clone() - } }