Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/wac-graph/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1533,7 +1533,7 @@ impl<'a> CompositionGraphEncoder<'a> {
}

// Next encode the imports
for (name, kind) in aggregator.iter() {
for (name, kind) in aggregator.imports() {
log::debug!("import `{name}` is being implicitly imported");
let index = self.import(state, name, aggregator.types(), kind);
encoded.insert(name, (kind.into(), index));
Expand Down
2 changes: 2 additions & 0 deletions crates/wac-graph/tests/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl GraphFile {
path = path.display()
)
})?,
None if path.is_dir() => Self::load_wit_package(test_case, &path)?,
_ => bail!(
"unexpected file extension for package file `{path}`",
path = package.path.display()
Expand Down Expand Up @@ -331,6 +332,7 @@ fn encoding() -> Result<()> {
})?
.into_composition_graph(&path, test_case)
.and_then(|graph| {
println!("{:?}", graph);
graph
.encode(EncodeOptions {
// We import the component definitions instead
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package foo:dependency;

interface types {
resource x;
}

world w {
export types;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package foo:bar;

world w {
export foo:dependency/types;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package foo:dependency;

interface types {
resource x;
}

world w {
export types;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package foo:baz;

world w {
use foo:dependency/types.{x};
import my-func: func() -> x;
// The test will fail whether this is here or not
import foo:dependency/types;
}
57 changes: 57 additions & 0 deletions crates/wac-graph/tests/graphs/implicit-resource-import/encoded.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
(component
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(import "foo:dependency/types" (instance (;0;) (type 0)))
(alias export 0 "x" (type (;1;)))
(import "x" (type (;2;) (eq 1)))
(alias export 0 "x" (type (;3;)))
(type (;4;)
(instance
(alias outer 1 3 (type (;0;)))
(export (;1;) "x" (type (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(export (;0;) "my-func" (func (type 3)))
)
)
(import "foo:test-import/my-interface" (instance (;1;) (type 4)))
(type (;5;)
(component
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(export (;0;) "foo:dependency/types" (instance (type 0)))
)
)
(import "unlocked-dep=<test:bar>" (component (;0;) (type 5)))
(instance (;2;) (instantiate 0))
(alias export 1 "my-func" (func (;0;)))
(alias export 2 "foo:dependency/types" (instance (;3;)))
(type (;6;)
(component
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(import "foo:dependency/types" (instance (;0;) (type 0)))
(alias outer 1 3 (type (;1;)))
(import "x" (type (;2;) (eq 1)))
(type (;3;) (own 2))
(type (;4;) (func (result 3)))
(import "my-func" (func (;0;) (type 4)))
)
)
(import "unlocked-dep=<test:baz>" (component (;1;) (type 6)))
(instance (;4;) (instantiate 1
(with "foo:dependency/types" (instance 3))
(with "my-func" (func 0))
(with "x" (type 2))
)
)
)
54 changes: 54 additions & 0 deletions crates/wac-graph/tests/graphs/implicit-resource-import/graph.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"packages": [
{
"name": "foo:import",
"path": "import"
},
{
"name": "test:bar",
"path": "bar"
},
{
"name": "test:baz",
"path": "baz"
}
],
"nodes": [
{
"type": "import",
"name": "foo:test-import/my-interface",
"package": 0,
"export": "foo:test-import/my-interface"
},
{
"type": "instantiation",
"package": 1
},
{
"type": "alias",
"source": 0,
"export": "my-func"
},
{
"type": "alias",
"source": 1,
"export": "foo:dependency/types"
},
{
"type": "instantiation",
"package": 2
}
],
"arguments": [
{
"source": 2,
"target": 4,
"name": "my-func"
},
{
"source": 3,
"target": 4,
"name": "foo:dependency/types"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package foo:dependency;

interface types {
resource x;
}

world w {
export types;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package foo:test-import;

world w {
export my-interface;
}

interface my-interface{
use foo:dependency/types.{x};
my-func: func() -> x;
}
38 changes: 27 additions & 11 deletions crates/wac-types/src/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct TypeAggregator {
/// The aggregated types collection.
types: Types,
/// The map from import name to aggregated item kind.
names: IndexMap<String, ItemKind>,
imports: IndexMap<String, ItemKind>,
/// A map from foreign type to remapped local type.
remapped: HashMap<Type, Type>,
/// A map of interface names to remapped interface id.
Expand All @@ -41,9 +41,9 @@ impl TypeAggregator {
&self.types
}

/// Iterates the named types in the aggregator.
pub fn iter(&self) -> impl Iterator<Item = (&str, ItemKind)> {
self.names.iter().map(|(n, k)| (n.as_str(), *k))
/// Iterates the imported types in the aggregator.
pub fn imports(&self) -> impl Iterator<Item = (&str, ItemKind)> {
self.imports.iter().map(|(n, k)| (n.as_str(), *k))
}

/// Aggregates a item kind from a specified type collection using the given
Expand All @@ -60,13 +60,13 @@ impl TypeAggregator {
// First check if this import has already been remapped into our
// types collection.
// If it has already been remapped, do a merge; otherwise, remap it.
if let Some(existing) = self.names.get(name).copied() {
if let Some(existing) = self.imports.get(name).copied() {
self.merge_item_kind(existing, types, kind, checker)?;
return Ok(self);
}

let ty = self.remap_item_kind(types, kind, checker)?;
let prev = self.names.insert(name.to_string(), ty);
let remapped = self.remap_item_kind(types, kind, checker)?;
let prev = self.imports.insert(name.to_string(), remapped);
assert!(prev.is_none());
Ok(self)
}
Expand Down Expand Up @@ -549,11 +549,27 @@ impl TypeAggregator {
alias: resource
.alias
.map(|a| -> Result<_> {
let owner = a
.owner
.map(|id| {
// There's no need to merge the interface here as
// merging is done as part of the interface remapping
self.remap_interface(types, id, checker)
})
.transpose()?;
// If there is an owning interface, ensure it is imported
if let Some(owner) = owner {
let name = self.types()[owner]
.id
.as_deref()
.expect("interface has no id");
if !self.imports.contains_key(name) {
self.imports
.insert(name.to_owned(), ItemKind::Instance(owner));
}
}
Ok(ResourceAlias {
owner: a
.owner
.map(|id| self.remap_interface(types, id, checker))
.transpose()?,
owner,
source: self.remap_resource(types, a.source, checker)?,
})
})
Expand Down