Skip to content

Commit

Permalink
fix(provider-wit-bindgen): type aliasing for nested types
Browse files Browse the repository at this point in the history
When using a type alias in WIT (ex. `type str-list = vec<string>`),
if that type is inside an interface and used from another interface,
there is an extra alias made to it.

Since bindgen sees *both* the "real" alias (in Rust `type StrList =
Vec<String>`) and the local binding level alias (in Rust `type StrList
= super::some::iface::StrList`), we need to make sure that the "real"
alias is the one that is hoisted to the top.

This commit adds some checks to ensure that the alias that is *not* a
reference is sure to be hoisted to the top (all generated code uses
`T`, not `super::some::iface::T`). This is a a shortcut to avoid
building a type reference graph.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
  • Loading branch information
vados-cosmonic committed Mar 4, 2024
1 parent 20421f1 commit 5a3a37a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
24 changes: 20 additions & 4 deletions crates/provider-wit-bindgen-macro/src/bindgen_visitor.rs
Expand Up @@ -456,10 +456,11 @@ impl VisitMut for WitBindgenOutputVisitor {
..
} = cloned_t;

// If the type that we're about to process has `super::`s attached, we need to translate those
// If the type alias that we're about to process has `super::`s attached, we need to translate those
// to the actual types they *should* be, which are likely hanging off the crate or some other
// dep like `wasmtime` (ex. `wasmtime::component::Resource`)
if count_preceeding_supers(item_ty.as_ref()) > 0 {
let preceeding_super_count = count_preceeding_supers(item_ty.as_ref());
if preceeding_super_count > 0 {
if let Type::Path(ty_path) = item_ty.as_mut() {
// Create a cloned version fo the original path to use for modifications
let cloned_ty_path = ty_path.clone();
Expand Down Expand Up @@ -500,11 +501,26 @@ impl VisitMut for WitBindgenOutputVisitor {
// Having both the type declaration and the top level struct/enum declaration would cause a conflict
if !self.serde_extended_enums.contains_key(&t.ident.to_string())
&& !self
.serde_extended_structs
.contains_key(&t.ident.to_string())
.serde_extended_structs
.contains_key(&t.ident.to_string())
// We exclude built-in wasi types here because they *should*
// be implemented & brought in as enums/structs
&& !self.is_wasi_builtin()
// If this type alias has no preceeding `super::` count and it has not been seen, it's most likely the
// resolved alias to a basic Rust type:
// ```
// type T = vec<u8>
// ```
//
// Otherwise, if there *is* a preceeding `super::` count, it likely looks like this:
// ```
// type T = super::some::dep::T
// ```
// We should avoid overwriting the basic Rust type alias, since that one should be hoisted to the top.
// All code will deal with the types that the top level(i.e. generated code will contain `T`, not `super::some::dep::T`)
// otherwise, we can add if it's not overlapping with an existing entry.
&& (preceeding_super_count == 0
|| !self.type_lookup.contains_key(&t.ident.to_string()))
{
// Add the type to the lookup so it can be used later for fully qualified names
self.type_lookup
Expand Down
5 changes: 4 additions & 1 deletion crates/provider-wit-bindgen-macro/src/lib.rs
Expand Up @@ -397,11 +397,14 @@ pub fn generate(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
.type_lookup
.iter()
.filter_map(|(_, (_, ty))| {
// If the name of the type is identical to a bindgen-produced struct that will
// If the name of the type is identical to a bindgen-produced struct or enum that will
// be added later, this was likely a type alias -- we won't need it
if visitor
.serde_extended_structs
.contains_key(&ty.ident.to_string())
|| visitor
.serde_extended_enums
.contains_key(&ty.ident.to_string())
{
None
} else {
Expand Down
2 changes: 1 addition & 1 deletion crates/provider-wit-bindgen-macro/src/wit.rs
Expand Up @@ -865,7 +865,7 @@ impl WitFunctionLatticeTranslationStrategy {
.await?;

if let Some(err) = response.error {
Err(::wasmcloud_provider_wit_bindgen::deps::wasmcloud_provider_sdk::error::InvocationError::Failed(err.to_string()))
Err(::wasmcloud_provider_wit_bindgen::deps::wasmcloud_provider_sdk::error::InvocationError::Unexpected(err.to_string()))
} else {
Ok(::wasmcloud_provider_wit_bindgen::deps::wasmcloud_provider_sdk::deserialize(&response.msg)?)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/providers/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5a3a37a

Please sign in to comment.