Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix aggregation of imports. #67

Merged
merged 3 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions crates/wac-graph/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ wasmprinter = { workspace = true }
wat = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
wit-component = { workspace = true, features = ["dummy-module"] }
wit-parser = { workspace = true }

[features]
serde = ["dep:serde", "wac-types/serde"]
8 changes: 7 additions & 1 deletion crates/wac-graph/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@ impl<'a> CompositionGraphEncoder<'a> {
let mut arguments = Vec::new();
let mut encoded = HashMap::new();
let mut cache = Default::default();
let mut checker = SubtypeChecker::new(&mut cache);

// Enumerate the instantiation nodes and populate the import types
for node in self.0.nodes() {
Expand Down Expand Up @@ -1379,7 +1380,7 @@ impl<'a> CompositionGraphEncoder<'a> {
}

aggregator = aggregator
.aggregate(name, package.types(), *kind, &mut cache)
.aggregate(name, package.types(), *kind, &mut checker)
.map_err(|e| Error::ImportTypeMergeConflict {
import: name.clone(),
source: e,
Expand All @@ -1404,6 +1405,11 @@ impl<'a> CompositionGraphEncoder<'a> {
},
);

// Ensure we insert an instance index into the current scope
if let ItemKind::Instance(id) = kind {
state.current.instances.insert(id, index);
}

let prev = encoded.insert(name, (kind.into(), index));
assert!(prev.is_none());
}
Expand Down
58 changes: 52 additions & 6 deletions crates/wac-graph/tests/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ use semver::Version;
use serde::Deserialize;
use std::{
collections::HashMap,
ffi::OsStr,
fs::{self, File},
path::{Path, PathBuf},
};
use wac_graph::{types::Package, CompositionGraph, EncodeOptions, NodeId, PackageId};
use wit_component::{ComponentEncoder, StringEncoding};
use wit_parser::Resolve;

/// Represents a node to add to a composition graph.
#[derive(Deserialize)]
Expand Down Expand Up @@ -118,12 +121,52 @@ impl GraphFile {

for (index, package) in self.packages.iter().enumerate() {
let path = root.join(&package.path);
let bytes = wat::parse_file(&path).with_context(|| {
format!(
"failed to parse package `{path}` for test case `{test_case}`",
path = path.display()
)
})?;
let bytes = match path.extension().and_then(OsStr::to_str) {
Some("wit") => {
let mut resolve = Resolve::default();
let id = resolve.push_file(&path).with_context(|| {
format!(
"failed to parse package file `{path}` for test case `{test_case}`",
path = path.display()
)
})?;
let world = resolve.select_world(id, None).with_context(|| {
format!(
"failed to select world from `{path}` for test case `{test_case}`",
path = path.display()
)
})?;

let mut module = wit_component::dummy_module(&resolve, world);
wit_component::embed_component_metadata(
&mut module,
&resolve,
world,
StringEncoding::default(),
)
.with_context(|| {
format!(
"failed to embed component metadata from package `{path}` for test case `{test_case}`",
path = path.display()
)
})?;

let encoder = ComponentEncoder::default().validate(true).module(&module)?;
encoder
.encode()
.with_context(|| format!("failed to encode a component from module derived from package `{path}` for test case `{test_case}`", path = path.display()))?
}
Some("wat") => wat::parse_file(&path).with_context(|| {
format!(
"failed to parse package `{path}` for test case `{test_case}`",
path = path.display()
)
})?,
_ => bail!(
"unexpected file extension for package file `{path}`",
path = package.path.display()
),
};

let package = Package::from_bytes(&package.name, package.version.as_ref(), bytes)
.with_context(|| {
Expand Down Expand Up @@ -226,6 +269,9 @@ impl GraphFile {
/// * [required] `graph.json` - a JSON representation of a composition graph
/// (see above for serialization format).
/// * [optional] `*.wat` - packages (i.e. components) referenced from `graph.json`.
/// * [optional] `*.wit` - packages (i.e. components) referenced from `graph.json`;
/// the file is expected to contain a single world representing the world of
/// the component; a dummy module will be created to implement the component.
///
/// And the output files are one of the following:
///
Expand Down
15 changes: 15 additions & 0 deletions crates/wac-graph/tests/graphs/merged-usings/component.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package foo:bar;

interface baz {
resource x;
}

interface qux {
use baz.{x};
f: func() -> x;
}

world w {
import qux;
export qux;
}
198 changes: 198 additions & 0 deletions crates/wac-graph/tests/graphs/merged-usings/encoded.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
(component
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(import "foo:bar/baz" (instance (;0;) (type 0)))
(alias export 0 "x" (type (;1;)))
(type (;2;)
(instance
(alias outer 1 1 (type (;0;)))
(export (;1;) "x" (type (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(export (;0;) "f" (func (type 3)))
)
)
(import "foo:bar/qux" (instance (;1;) (type 2)))
(component (;0;)
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(import "foo:bar/baz" (instance (;0;) (type 0)))
(alias export 0 "x" (type (;1;)))
(type (;2;)
(instance
(alias outer 1 1 (type (;0;)))
(export (;1;) "x" (type (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(export (;0;) "f" (func (type 3)))
)
)
(import "foo:bar/qux" (instance (;1;) (type 2)))
(core module (;0;)
(type (;0;) (func (param i32)))
(type (;1;) (func (result i32)))
(type (;2;) (func (param i32 i32 i32 i32) (result i32)))
(import "foo:bar/baz" "[resource-drop]x" (func (;0;) (type 0)))
(import "foo:bar/qux" "f" (func (;1;) (type 1)))
(func (;2;) (type 1) (result i32)
unreachable
)
(func (;3;) (type 2) (param i32 i32 i32 i32) (result i32)
unreachable
)
(memory (;0;) 0)
(export "foo:bar/qux#f" (func 2))
(export "memory" (memory 0))
(export "cabi_realloc" (func 3))
(@producers
(processed-by "wit-component" "0.202.0")
)
)
(alias export 0 "x" (type (;3;)))
(core func (;0;) (canon resource.drop 3))
(core instance (;0;)
(export "[resource-drop]x" (func 0))
)
(alias export 1 "f" (func (;0;)))
(core func (;1;) (canon lower (func 0)))
(core instance (;1;)
(export "f" (func 1))
)
(core instance (;2;) (instantiate 0
(with "foo:bar/baz" (instance 0))
(with "foo:bar/qux" (instance 1))
)
)
(alias core export 2 "memory" (core memory (;0;)))
(alias core export 2 "cabi_realloc" (core func (;2;)))
(alias export 0 "x" (type (;4;)))
(type (;5;) (own 4))
(type (;6;) (func (result 5)))
(alias core export 2 "foo:bar/qux#f" (core func (;3;)))
(func (;1;) (type 6) (canon lift (core func 3)))
(alias export 0 "x" (type (;7;)))
(component (;0;)
(import "import-type-x" (type (;0;) (sub resource)))
(import "import-type-x0" (type (;1;) (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(import "import-func-f" (func (;0;) (type 3)))
(export (;4;) "x" (type 0))
(type (;5;) (own 4))
(type (;6;) (func (result 5)))
(export (;1;) "f" (func 0) (func (type 6)))
)
(instance (;2;) (instantiate 0
(with "import-func-f" (func 1))
(with "import-type-x" (type 7))
(with "import-type-x0" (type 4))
)
)
(export (;3;) "foo:bar/qux" (instance 2))
(@producers
(processed-by "wit-component" "0.202.0")
)
)
(instance $component2 (;2;) (instantiate 0
(with "foo:bar/baz" (instance 0))
(with "foo:bar/qux" (instance 1))
)
)
(alias export $component2 "foo:bar/qux" (instance $alias (;3;)))
(component (;1;)
(type (;0;)
(instance
(export (;0;) "x" (type (sub resource)))
)
)
(import "foo:bar/baz" (instance (;0;) (type 0)))
(alias export 0 "x" (type (;1;)))
(type (;2;)
(instance
(alias outer 1 1 (type (;0;)))
(export (;1;) "x" (type (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(export (;0;) "f" (func (type 3)))
)
)
(import "foo:bar/qux" (instance (;1;) (type 2)))
(core module (;0;)
(type (;0;) (func (param i32)))
(type (;1;) (func (result i32)))
(type (;2;) (func (param i32 i32 i32 i32) (result i32)))
(import "foo:bar/baz" "[resource-drop]x" (func (;0;) (type 0)))
(import "foo:bar/qux" "f" (func (;1;) (type 1)))
(func (;2;) (type 1) (result i32)
unreachable
)
(func (;3;) (type 2) (param i32 i32 i32 i32) (result i32)
unreachable
)
(memory (;0;) 0)
(export "foo:bar/qux#f" (func 2))
(export "memory" (memory 0))
(export "cabi_realloc" (func 3))
(@producers
(processed-by "wit-component" "0.202.0")
)
)
(alias export 0 "x" (type (;3;)))
(core func (;0;) (canon resource.drop 3))
(core instance (;0;)
(export "[resource-drop]x" (func 0))
)
(alias export 1 "f" (func (;0;)))
(core func (;1;) (canon lower (func 0)))
(core instance (;1;)
(export "f" (func 1))
)
(core instance (;2;) (instantiate 0
(with "foo:bar/baz" (instance 0))
(with "foo:bar/qux" (instance 1))
)
)
(alias core export 2 "memory" (core memory (;0;)))
(alias core export 2 "cabi_realloc" (core func (;2;)))
(alias export 0 "x" (type (;4;)))
(type (;5;) (own 4))
(type (;6;) (func (result 5)))
(alias core export 2 "foo:bar/qux#f" (core func (;3;)))
(func (;1;) (type 6) (canon lift (core func 3)))
(alias export 0 "x" (type (;7;)))
(component (;0;)
(import "import-type-x" (type (;0;) (sub resource)))
(import "import-type-x0" (type (;1;) (eq 0)))
(type (;2;) (own 1))
(type (;3;) (func (result 2)))
(import "import-func-f" (func (;0;) (type 3)))
(export (;4;) "x" (type 0))
(type (;5;) (own 4))
(type (;6;) (func (result 5)))
(export (;1;) "f" (func 0) (func (type 6)))
)
(instance (;2;) (instantiate 0
(with "import-func-f" (func 1))
(with "import-type-x" (type 7))
(with "import-type-x0" (type 4))
)
)
(export (;3;) "foo:bar/qux" (instance 2))
(@producers
(processed-by "wit-component" "0.202.0")
)
)
(instance $component1 (;4;) (instantiate 1
(with "foo:bar/qux" (instance $alias))
(with "foo:bar/baz" (instance 0))
)
)
(alias export $component1 "foo:bar/qux" (instance $export (;5;)))
(export (;6;) "foo:bar/qux" (instance $export))
)
Loading
Loading