diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs index c7fb0f51a7..5642023dba 100644 --- a/crates/component-macro/tests/codegen.rs +++ b/crates/component-macro/tests/codegen.rs @@ -107,6 +107,33 @@ mod with_key_and_resources { } } +mod trappable_errors_with_versioned_and_unversioned_packages { + wasmtime::component::bindgen!({ + inline: " + package foo:foo@0.1.0; + + interface a { + variant error { + other(string), + } + + f: func() -> result<_, error>; + } + + world foo { + import a; + } + ", + path: "tests/codegen/unversioned-foo.wit", + trappable_error_type: { + "foo:foo/a@0.1.0/error" => MyX, + }, + }); + + #[allow(dead_code)] + type MyX = u64; +} + mod trappable_errors { wasmtime::component::bindgen!({ inline: " diff --git a/crates/component-macro/tests/codegen/unversioned-foo.wit b/crates/component-macro/tests/codegen/unversioned-foo.wit new file mode 100644 index 0000000000..a7b3bb616c --- /dev/null +++ b/crates/component-macro/tests/codegen/unversioned-foo.wit @@ -0,0 +1,12 @@ +package foo:foo; + +interface a { + variant error { + other(string), + } + g: func() -> result<_, error>; +} + +world nope { + import a; +} \ No newline at end of file diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index 7042eb7f0f..a18543d382 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -1,6 +1,6 @@ use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode}; use crate::types::{TypeInfo, Types}; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use heck::*; use indexmap::{IndexMap, IndexSet}; use std::collections::{BTreeMap, HashMap, HashSet}; @@ -859,9 +859,13 @@ fn resolve_type_in_package(resolve: &Resolve, wit_path: &str) -> anyhow::Result< .flat_map(|l| l) .collect::>(); + let mut found_interface = false; + // Look for an interface whose assigned prefix starts `wit_path`. Not // exactly the most efficient thing ever but is sufficient for now. for (id, interface) in resolve.interfaces.iter() { + found_interface = true; + let iface_name = match &interface.name { Some(name) => name, None => continue, @@ -879,15 +883,20 @@ fn resolve_type_in_package(resolve: &Resolve, wit_path: &str) -> anyhow::Result< Some(rest) => rest, None => continue, }; - let wit_path = wit_path - .strip_prefix('/') - .ok_or_else(|| anyhow!("expected `/` after interface name"))?; - return interface - .types - .get(wit_path) - .copied() - .ok_or_else(|| anyhow!("no types found to match `{wit_path}` in interface")); + let wit_path = match wit_path.strip_prefix('/') { + Some(rest) => rest, + None => continue, + }; + + match interface.types.get(wit_path).copied() { + Some(type_id) => return Ok(type_id), + None => continue, + } + } + + if found_interface { + bail!("no types found to match `{wit_path}` in interface"); } bail!("no package/interface found to match `{wit_path}`")