From 01c0828bb57439286afddbde6372183f84510bca Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Wed, 29 Nov 2023 17:59:42 -0800 Subject: [PATCH] Fix duplicate import encoding. This fixes a bug where a duplicate import might occur when an import with dependencies on other interfaces is encoded and then later on an import for one of those dependencies is also explicitly encoded. It skips the import if it has already been imported and also ensures that the full interface definition is provided when encoding at the root state (i.e. for the composition itself and not an instance/component type). As such, we don't need to process dependencies of implicit imports during resolution. --- crates/wac-parser/src/resolution/ast.rs | 22 -------------------- crates/wac-parser/src/resolution/encoding.rs | 9 +++++++- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/crates/wac-parser/src/resolution/ast.rs b/crates/wac-parser/src/resolution/ast.rs index 2c717b6..2fcc2be 100644 --- a/crates/wac-parser/src/resolution/ast.rs +++ b/crates/wac-parser/src/resolution/ast.rs @@ -1768,28 +1768,6 @@ impl<'a> AstResolver<'a> { ) -> ResolutionResult { assert!(state.scopes.is_empty()); - // If the item is an instance, we need to recurse on its dependencies - if let ItemKind::Instance(id) = kind { - let interface = &self.definitions.interfaces[id]; - let deps = interface - .uses - .keys() - .map(|id| { - ( - *id, - self.definitions.interfaces[*id] - .id - .as_ref() - .unwrap() - .clone(), - ) - }) - .collect::>(); - for (dep, name) in deps { - self.implicit_import(state, name, ItemKind::Instance(dep), package, span)?; - } - } - if let Some(import) = state.imports.get(&name) { // Check if the implicit import would conflict with an explicit import if import.package.is_none() { diff --git a/crates/wac-parser/src/resolution/encoding.rs b/crates/wac-parser/src/resolution/encoding.rs index 78196e8..c538d43 100644 --- a/crates/wac-parser/src/resolution/encoding.rs +++ b/crates/wac-parser/src/resolution/encoding.rs @@ -167,6 +167,13 @@ impl<'a> Encoder<'a> { ItemKind::Type(ty) => ComponentTypeRef::Type(TypeBounds::Eq(encoder.ty(state, ty)?)), ItemKind::Func(id) => ComponentTypeRef::Func(encoder.ty(state, Type::Func(id))?), ItemKind::Instance(id) => { + // Check to see if the instance has already been imported + // This may occur when an interface uses another + if let Some(index) = state.current.instances.get(&id) { + log::debug!("skipping import of interface {id} as it was already imported with instance index {index}", id = id.index()); + return Ok(*index); + } + ComponentTypeRef::Instance(encoder.ty(state, Type::Interface(id))?) } ItemKind::Component(id) => { @@ -710,7 +717,7 @@ impl<'a> TypeEncoder<'a> { log::debug!("encoding dependency on interface {id}", id = id.index()); - let index = self.instance(state, id, true)?; + let index = self.instance(state, id, !state.scopes.is_empty())?; let import_index = state.current.encodable.instance_count(); state