Fail with Trap in Instance::new() instead of Error (#683)

This commit is contained in:
Yury Delendik
2019-12-30 16:25:16 -06:00
committed by GitHub
parent 51f3ac0c45
commit 681445b18b
18 changed files with 172 additions and 86 deletions

View File

@@ -7,7 +7,7 @@ use wasmtime::*;
struct HelloCallback;
impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
println!("Calling back...");
println!("> Hello World!");
Ok(())

View File

@@ -7,7 +7,7 @@ use wasmtime::*;
struct Callback;
impl Callable for Callback {
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), Trap> {
println!("Calling back...");
println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64());

View File

@@ -1,7 +1,7 @@
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::trampoline::{generate_func_export, take_api_trap};
use crate::trap::Trap;
use crate::trap::{Trap, TrapInfo};
use crate::types::FuncType;
use crate::values::Val;
use std::rc::Rc;
@@ -18,7 +18,7 @@ use wasmtime_runtime::Export;
/// struct TimesTwo;
///
/// impl wasmtime::Callable for TimesTwo {
/// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<wasmtime::Trap>> {
/// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), wasmtime::Trap> {
/// let mut value = params[0].unwrap_i32();
/// value *= 2;
/// results[0] = value.into();
@@ -75,7 +75,7 @@ use wasmtime_runtime::Export;
/// let results = run_function
/// .borrow()
/// .call(&[original.into()])
/// .map_err(|trap| trap.borrow().to_string())?;
/// .map_err(|trap| trap.to_string())?;
///
/// // Compare that the results returned matches what we expect.
/// assert_eq!(original * 2, results[0].unwrap_i32());
@@ -87,11 +87,11 @@ pub trait Callable {
/// `params` is an immutable list of parameters provided to the function.
/// `results` is mutable list of results to be potentially set by your
/// function. Produces a `Trap` if the function encounters any errors.
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
}
pub(crate) trait WrappedCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
fn signature(&self) -> &ir::Signature {
match self.wasmtime_export() {
Export::Function { signature, .. } => signature,
@@ -119,7 +119,7 @@ impl WasmtimeFn {
}
impl WrappedCallable for WasmtimeFn {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
use std::cmp::max;
use std::mem;
@@ -150,7 +150,7 @@ impl WrappedCallable for WasmtimeFn {
.context()
.compiler()
.get_published_trampoline(body, &signature, value_size)
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
.map_err(|e| Trap::new(format!("trampoline error: {:?}", e)))?;
// Call the trampoline.
if let Err(message) = unsafe {
@@ -160,8 +160,9 @@ impl WrappedCallable for WasmtimeFn {
values_vec.as_mut_ptr() as *mut u8,
)
} {
let trap = take_api_trap().unwrap_or_else(|| HostRef::new(Trap::new(message)));
return Err(trap);
let trap = take_api_trap()
.unwrap_or_else(|| HostRef::new(TrapInfo::new(format!("call error: {}", message))));
return Err(trap.into());
}
// Load the return values out of `values_vec`.
@@ -206,7 +207,7 @@ impl NativeCallable {
}
impl WrappedCallable for NativeCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
self.callable.call(params, results)
}
fn wasmtime_handle(&self) -> &InstanceHandle {

View File

@@ -147,7 +147,7 @@ impl Func {
self.r#type.results().len()
}
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, HostRef<Trap>> {
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
let mut results = vec![Val::null(); self.result_arity()];
self.callable.call(params, &mut results)?;
Ok(results.into_boxed_slice())

View File

@@ -4,8 +4,9 @@ use crate::module::Module;
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::trampoline::take_api_trap;
use crate::trap::Trap;
use crate::types::{ExportType, ExternType};
use anyhow::Result;
use anyhow::{Error, Result};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
@@ -31,7 +32,7 @@ pub fn instantiate_in_context(
imports: Vec<(String, String, Extern)>,
mut context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>)> {
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
let mut contexts = HashSet::new();
let debug_info = context.debug_info();
let mut resolver = SimpleResolver { imports };
@@ -42,10 +43,12 @@ pub fn instantiate_in_context(
exports,
debug_info,
)
.map_err(|e| {
// TODO wrap HostRef<Trap> into Error
drop(take_api_trap());
e
.map_err(|e| -> Error {
if let Some(trap) = take_api_trap() {
Trap::from(trap).into()
} else {
e.into()
}
})?;
contexts.insert(context);
Ok((instance, contexts))
@@ -68,7 +71,7 @@ impl Instance {
store: &HostRef<Store>,
module: &HostRef<Module>,
externs: &[Extern],
) -> Result<Instance> {
) -> Result<Instance, Error> {
let context = store.borrow_mut().context().clone();
let exports = store.borrow_mut().global_exports().clone();
let imports = module

View File

@@ -28,6 +28,6 @@ pub use crate::instance::Instance;
pub use crate::module::Module;
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
pub use crate::runtime::{Config, Engine, Store};
pub use crate::trap::Trap;
pub use crate::trap::{FrameInfo, Trap, TrapInfo};
pub use crate::types::*;
pub use crate::values::*;

View File

@@ -96,6 +96,7 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *m
0
}
Err(trap) => {
let trap = trap.trap_info_unchecked();
record_api_trap(trap);
1
}

View File

@@ -1,7 +1,7 @@
use std::cell::Cell;
use crate::r#ref::HostRef;
use crate::Trap;
use crate::TrapInfo;
use wasmtime_environ::ir::{SourceLoc, TrapCode};
use wasmtime_environ::TrapInformation;
use wasmtime_jit::trampoline::binemit;
@@ -10,10 +10,10 @@ use wasmtime_jit::trampoline::binemit;
pub const API_TRAP_CODE: TrapCode = TrapCode::User(13);
thread_local! {
static RECORDED_API_TRAP: Cell<Option<HostRef<Trap>>> = Cell::new(None);
static RECORDED_API_TRAP: Cell<Option<HostRef<TrapInfo>>> = Cell::new(None);
}
pub fn record_api_trap(trap: HostRef<Trap>) {
pub fn record_api_trap(trap: HostRef<TrapInfo>) {
RECORDED_API_TRAP.with(|data| {
let trap = Cell::new(Some(trap));
data.swap(&trap);
@@ -24,7 +24,7 @@ pub fn record_api_trap(trap: HostRef<Trap>) {
});
}
pub fn take_api_trap() -> Option<HostRef<Trap>> {
pub fn take_api_trap() -> Option<HostRef<TrapInfo>> {
RECORDED_API_TRAP.with(|data| data.take())
}

View File

@@ -1,11 +1,88 @@
use crate::instance::Instance;
use crate::r#ref::HostRef;
use std::fmt;
use std::sync::{Arc, Mutex};
use thiserror::Error;
#[derive(Debug)]
pub struct FrameInfo;
impl FrameInfo {
pub fn instance(&self) -> *const Instance {
unimplemented!("FrameInfo::instance");
}
pub fn func_index() -> usize {
unimplemented!("FrameInfo::func_index");
}
pub fn func_offset() -> usize {
unimplemented!("FrameInfo::func_offset");
}
pub fn module_offset() -> usize {
unimplemented!("FrameInfo::module_offset");
}
}
#[derive(Debug)]
pub struct TrapInfo {
message: String,
trace: Vec<FrameInfo>,
}
impl TrapInfo {
pub fn new<I: Into<String>>(message: I) -> Self {
Self {
message: message.into(),
trace: vec![],
}
}
/// Returns a reference the `message` stored in `Trap`.
pub fn message(&self) -> &str {
&self.message
}
pub fn origin(&self) -> Option<&FrameInfo> {
self.trace.first()
}
pub fn trace(&self) -> &[FrameInfo] {
&self.trace
}
}
/// A struct to hold unsafe TrapInfo host reference, designed
/// to be Send-able. The only access for it provided via the
/// Trap::trap_info_unchecked() method.
struct UnsafeTrapInfo(HostRef<TrapInfo>);
impl UnsafeTrapInfo {
fn trap_info(&self) -> HostRef<TrapInfo> {
self.0.clone()
}
}
unsafe impl Send for UnsafeTrapInfo {}
impl fmt::Debug for UnsafeTrapInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UnsafeTrapInfo")
}
}
/// A struct representing an aborted instruction execution, with a message
/// indicating the cause.
#[derive(Error, Debug)]
#[error("Wasm trap: {message}")]
pub struct Trap {
message: String,
info: Arc<Mutex<UnsafeTrapInfo>>,
}
fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) {
(t, t)
}
impl Trap {
@@ -15,20 +92,26 @@ impl Trap {
/// let trap = wasmtime::Trap::new("unexpected error");
/// assert_eq!("unexpected error", trap.message());
/// ```
pub fn new<I: Into<String>>(message: I) -> Trap {
Self {
message: message.into(),
}
}
/// Create a `Trap` without defining a message for the trap. Mostly useful
/// for prototypes and tests.
pub fn fake() -> Trap {
Self::new("TODO trap")
pub fn new<I: Into<String>>(message: I) -> Self {
Trap::from(HostRef::new(TrapInfo::new(message)))
}
/// Returns a reference the `message` stored in `Trap`.
pub fn message(&self) -> &str {
&self.message
}
/// Returns inner TrapInfo assotiated with the Trap.
/// The method is unsafe: obtained TrapInfo is not thread safe.
pub(crate) unsafe fn trap_info_unchecked(&self) -> HostRef<TrapInfo> {
self.info.lock().unwrap().trap_info()
}
}
impl From<HostRef<TrapInfo>> for Trap {
fn from(trap_info: HostRef<TrapInfo>) -> Self {
let message = trap_info.borrow().message().to_string();
let info = Arc::new(Mutex::new(UnsafeTrapInfo(trap_info)));
Trap { message, info }
}
}

View File

@@ -8,7 +8,7 @@
use super::{
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
TableType, Trap, Val, ValType,
TableType, Trap, TrapInfo, Val, ValType,
};
use std::rc::Rc;
use std::{mem, ptr, slice};
@@ -317,7 +317,7 @@ pub type wasm_message_t = wasm_name_t;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_trap_t {
trap: HostRef<Trap>,
trap_info: HostRef<TrapInfo>,
}
#[repr(C)]
#[derive(Clone)]
@@ -469,7 +469,8 @@ pub unsafe extern "C" fn wasm_func_call(
ptr::null_mut()
}
Err(trap) => {
let trap = Box::new(wasm_trap_t { trap });
let trap_info = trap.trap_info_unchecked();
let trap = Box::new(wasm_trap_t { trap_info });
Box::into_raw(trap)
}
}
@@ -539,7 +540,7 @@ impl wasm_val_t {
}
impl Callable for wasm_func_callback_t {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
let params = params
.iter()
.map(|p| wasm_val_t::from_val(p))
@@ -549,7 +550,8 @@ impl Callable for wasm_func_callback_t {
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
if !out.is_null() {
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
return Err((*trap).into());
let trap_info: HostRef<TrapInfo> = (*trap).into();
return Err(Trap::from(trap_info));
}
for i in 0..results.len() {
results[i] = out_results[i].val();
@@ -558,9 +560,9 @@ impl Callable for wasm_func_callback_t {
}
}
impl Into<HostRef<Trap>> for wasm_trap_t {
fn into(self) -> HostRef<Trap> {
self.trap
impl Into<HostRef<TrapInfo>> for wasm_trap_t {
fn into(self) -> HostRef<TrapInfo> {
self.trap_info
}
}
@@ -571,7 +573,7 @@ struct CallbackWithEnv {
}
impl Callable for CallbackWithEnv {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
let params = params
.iter()
.map(|p| wasm_val_t::from_val(p))
@@ -581,7 +583,8 @@ impl Callable for CallbackWithEnv {
let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) };
if !out.is_null() {
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
return Err((*trap).into());
let trap_info: HostRef<TrapInfo> = (*trap).into();
return Err(Trap::from(trap_info));
}
for i in 0..results.len() {
results[i] = out_results[i].val();
@@ -677,12 +680,13 @@ pub unsafe extern "C" fn wasm_instance_new(
}
Box::into_raw(instance)
}
Err(_) => {
Err(trap) => {
if !result.is_null() {
// TODO Unwrap trap from error
let trap = Box::new(wasm_trap_t {
trap: HostRef::new(Trap::new("trap during instantiation".to_string())),
});
let trap_info = match trap.downcast::<Trap>() {
Ok(trap) => trap.trap_info_unchecked(),
Err(_) => HostRef::new(TrapInfo::new("instance error".to_string())),
};
let trap = Box::new(wasm_trap_t { trap_info });
(*result) = Box::into_raw(trap);
}
ptr::null_mut()
@@ -925,7 +929,7 @@ pub unsafe extern "C" fn wasm_trap_new(
}
let message = String::from_utf8_lossy(message).to_string();
let trap = Box::new(wasm_trap_t {
trap: HostRef::new(Trap::new(message)),
trap_info: HostRef::new(TrapInfo::new(message)),
});
Box::into_raw(trap)
}
@@ -933,7 +937,7 @@ pub unsafe extern "C" fn wasm_trap_new(
#[no_mangle]
pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) {
let mut buffer = Vec::new();
buffer.extend_from_slice((*trap).trap.borrow().message().as_bytes());
buffer.extend_from_slice((*trap).trap_info.borrow().message().as_bytes());
buffer.reserve_exact(1);
buffer.push(0);
(*out).set_buffer(buffer);

View File

@@ -20,7 +20,7 @@ fn test_import_calling_export() {
}
impl Callable for Callback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
self.other
.borrow()
.as_ref()

View File

@@ -7,8 +7,8 @@ fn test_trap_return() -> Result<(), String> {
struct HelloCallback;
impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
Err(HostRef::new(Trap::new("test 123")))
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
Err(Trap::new("test 123"))
}
}
@@ -32,7 +32,7 @@ fn test_trap_return() -> Result<(), String> {
let imports = vec![hello_func.into()];
let instance = Instance::new(&store, &module, imports.as_slice())
.map_err(|e| format!("failed to instantiate module: {}", e))?;
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0]
.func()
.expect("expected function export");
@@ -43,7 +43,7 @@ fn test_trap_return() -> Result<(), String> {
.err()
.expect("error calling function");
assert_eq!(e.borrow().message(), "test 123");
assert_eq!(e.message(), "test 123");
Ok(())
}

View File

@@ -10,7 +10,7 @@ use wasmtime::{
pub fn dummy_imports(
store: &HostRef<Store>,
import_tys: &[ImportType],
) -> Result<Vec<Extern>, HostRef<Trap>> {
) -> Result<Vec<Extern>, Trap> {
let mut imports = Vec::with_capacity(import_tys.len());
for imp in import_tys {
imports.push(match imp.ty() {
@@ -45,7 +45,7 @@ impl DummyFunc {
}
impl Callable for DummyFunc {
fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
for (ret_ty, result) in self.0.results().iter().zip(results) {
*result = dummy_value(ret_ty)?;
}
@@ -55,38 +55,38 @@ impl Callable for DummyFunc {
}
/// Construct a dummy value for the given value type.
pub fn dummy_value(val_ty: &ValType) -> Result<Val, HostRef<Trap>> {
pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
Ok(match val_ty {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0),
ValType::F64 => Val::F64(0),
ValType::V128 => {
return Err(HostRef::new(Trap::new(
return Err(Trap::new(
"dummy_value: unsupported function return type: v128".to_string(),
)))
))
}
ValType::AnyRef => {
return Err(HostRef::new(Trap::new(
return Err(Trap::new(
"dummy_value: unsupported function return type: anyref".to_string(),
)))
))
}
ValType::FuncRef => {
return Err(HostRef::new(Trap::new(
return Err(Trap::new(
"dummy_value: unsupported function return type: funcref".to_string(),
)))
))
}
})
}
/// Construct a dummy global for the given global type.
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, HostRef<Trap>> {
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, Trap> {
let val = dummy_value(ty.content())?;
Ok(Global::new(store, ty, val))
}
/// Construct a dummy table for the given table type.
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, HostRef<Trap>> {
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, Trap> {
let init_val = dummy_value(&ty.element())?;
Ok(Table::new(store, ty, init_val))
}

View File

@@ -82,7 +82,7 @@ impl wasmtime::Callable for WrappedFn {
&self,
params: &[wasmtime::Val],
returns: &mut [wasmtime::Val],
) -> Result<(), wasmtime::HostRef<wasmtime::Trap>> {
) -> Result<(), wasmtime::Trap> {
let gil = Python::acquire_gil();
let py = gil.python();

View File

@@ -91,7 +91,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
.borrow()
.call(&[])
{
bail!("trapped: {:?}", trap.borrow());
bail!("trapped: {:?}", trap);
}
Ok(())

View File

@@ -9,9 +9,9 @@ struct MyCall<F>(F);
impl<F> Callable for MyCall<F>
where
F: Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>>,
F: Fn(&[Val], &mut [Val]) -> Result<(), Trap>,
{
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
(self.0)(params, results)
}
}
@@ -19,7 +19,7 @@ where
fn wrap(
store: &HostRef<Store>,
ty: FuncType,
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>> + 'static,
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
) -> Func {
Func::new(store, ty, Rc::new(MyCall(callable)))
}

View File

@@ -36,7 +36,7 @@ pub struct WastContext {
enum Outcome<T = Vec<Val>> {
Ok(T),
Trap(HostRef<Trap>),
Trap(Trap),
}
impl WastContext {
@@ -101,7 +101,7 @@ impl WastContext {
.filter_map(|e| e.downcast_ref::<InstantiationError>())
.next();
if let Some(InstantiationError::StartTrap(msg)) = err {
return Ok(Outcome::Trap(HostRef::new(Trap::new(msg.clone()))));
return Ok(Outcome::Trap(Trap::new(msg.clone())));
}
return Err(e);
}
@@ -139,7 +139,7 @@ impl WastContext {
fn module(&mut self, instance_name: Option<&str>, module: &[u8]) -> Result<()> {
let instance = match self.instantiate(module)? {
Outcome::Ok(i) => i,
Outcome::Trap(e) => bail!("instantiation failed with: {}", e.borrow().message()),
Outcome::Trap(e) => bail!("instantiation failed with: {}", e.message()),
};
if let Some(name) = instance_name {
self.instances.insert(name.to_string(), instance.clone());
@@ -241,7 +241,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
},
@@ -254,7 +253,6 @@ impl WastContext {
bail!("{}\nexpected trap, got {:?}", context(span), values)
}
Outcome::Trap(t) => {
let t = t.borrow();
if t.message().contains(message) {
continue;
}
@@ -283,7 +281,6 @@ impl WastContext {
bail!("{}\nexpected trap, got {:?}", context(span), values)
}
Outcome::Trap(t) => {
let t = t.borrow();
if t.message().contains(message) {
continue;
}
@@ -315,7 +312,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}
@@ -340,7 +336,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}
@@ -365,7 +360,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}
@@ -390,7 +384,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}
@@ -415,7 +408,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}
@@ -440,7 +432,6 @@ impl WastContext {
}
}
Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message())
}
}

View File

@@ -349,7 +349,10 @@ fn instantiate_module(
})
.collect::<Result<Vec<_>, _>>()?;
let instance = HostRef::new(Instance::new(store, &module, &imports)?);
let instance = HostRef::new(match Instance::new(store, &module, &imports) {
Ok(instance) => instance,
Err(trap) => bail!("Failed to instantiate {:?}: {:?}", path, trap),
});
Ok((instance, module, data))
}