Skip to content

Commit e02dc7f

Browse files
authored
Merge pull request #22 from peterhuene/fix-merge
Fix merge of disjoint interfaces.
2 parents d95f15e + 0df7a51 commit e02dc7f

8 files changed

Lines changed: 105 additions & 2 deletions

File tree

crates/wac-parser/src/resolution/ast.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ impl<'a> AstResolver<'a> {
445445

446446
let mut ty = Interface {
447447
id: None,
448+
remapped_types: Default::default(),
448449
uses: Default::default(),
449450
exports: Default::default(),
450451
};
@@ -483,6 +484,7 @@ impl<'a> AstResolver<'a> {
483484

484485
let mut ty = Interface {
485486
id: Some(self.id(decl.id.string)),
487+
remapped_types: Default::default(),
486488
uses: Default::default(),
487489
exports: Default::default(),
488490
};
@@ -1898,7 +1900,13 @@ impl<'a> AstResolver<'a> {
18981900
.with_context(|| format!("mismatched type for export `{name}`")),
18991901
) {
19001902
(Ok(_), Ok(_)) => {
1901-
// The two are compatible, so do nothing
1903+
// The two are compatible, check for remapped type
1904+
match (*target_kind, *source_kind) {
1905+
(ItemKind::Type(new), ItemKind::Type(old)) if new != old => {
1906+
target.remapped_types.entry(new).or_default().insert(old);
1907+
}
1908+
_ => {}
1909+
}
19021910
}
19031911
(Err(e), _) | (_, Err(e)) => {
19041912
// Neither is a subtype of the other, so error

crates/wac-parser/src/resolution/encoding.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,17 @@ impl<'a> TypeEncoder<'a> {
620620
// Otherwise, export all exports
621621
for (name, kind) in &interface.exports {
622622
match kind {
623-
ItemKind::Type(_) | ItemKind::Resource(_) => {
623+
ItemKind::Type(ty) => {
624+
let index = self.export(state, name, *kind)?;
625+
626+
// Map the encoded type index to any remapped types.
627+
if let Some(prev) = interface.remapped_types.get(ty) {
628+
for ty in prev {
629+
state.current.type_indexes.insert(*ty, index);
630+
}
631+
}
632+
}
633+
ItemKind::Resource(_) => {
624634
self.export(state, name, *kind)?;
625635
}
626636
_ => {

crates/wac-parser/src/resolution/package.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ impl<'a> TypeConverter<'a> {
364364
let instance_ty = &types[id];
365365
let id = self.definitions.interfaces.alloc(Interface {
366366
id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
367+
remapped_types: Default::default(),
367368
uses: Default::default(),
368369
exports: IndexMap::with_capacity(instance_ty.exports.len()),
369370
});

crates/wac-parser/src/resolution/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,15 @@ pub struct Interface {
387387
///
388388
/// This may be `None` for inline interfaces.
389389
pub id: Option<String>,
390+
/// Represents a remapping of types that may occur when an interface is merged.
391+
///
392+
/// The map is from the type present in this interface to a set of types
393+
/// originating from the merged interfaces.
394+
///
395+
/// Encoding uses this map to populate the encoded type index map for the
396+
/// original types.
397+
#[serde(skip)]
398+
pub remapped_types: IndexMap<Type, IndexSet<Type>>,
390399
/// A map from used interface to set of used type export indexes.
391400
#[serde(serialize_with = "serialize_id_key_map")]
392401
pub uses: IndexMap<InterfaceId, IndexSet<usize>>,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package test:comp;
2+
3+
let a = new foo:bar {
4+
...
5+
};
6+
7+
let b = new foo:baz {
8+
...
9+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
(component
2+
(type (;0;)
3+
(instance
4+
(type (;0;) (record (field "x" u32)))
5+
(export (;1;) "x" (type (eq 0)))
6+
(type (;2;) (func (param "x" 1)))
7+
(export (;0;) "y" (func (type 2)))
8+
(type (;3;) (func (param "x" 1)))
9+
(export (;1;) "z" (func (type 3)))
10+
)
11+
)
12+
(import "foo:bar/baz" (instance (;0;) (type 0)))
13+
(type (;1;)
14+
(component
15+
(type (;0;)
16+
(instance
17+
(type (;0;) (record (field "x" u32)))
18+
(export (;1;) "x" (type (eq 0)))
19+
(type (;2;) (func (param "x" 1)))
20+
(export (;0;) "y" (func (type 2)))
21+
)
22+
)
23+
(import "foo:bar/baz" (instance (;0;) (type 0)))
24+
)
25+
)
26+
(import "unlocked-dep=<foo:bar>" (component (;0;) (type 1)))
27+
(instance (;1;) (instantiate 0
28+
(with "foo:bar/baz" (instance 0))
29+
)
30+
)
31+
(type (;2;)
32+
(component
33+
(type (;0;)
34+
(instance
35+
(type (;0;) (record (field "x" u32)))
36+
(export (;1;) "x" (type (eq 0)))
37+
(type (;2;) (func (param "x" 1)))
38+
(export (;0;) "z" (func (type 2)))
39+
)
40+
)
41+
(import "foo:bar/baz" (instance (;0;) (type 0)))
42+
)
43+
)
44+
(import "unlocked-dep=<foo:baz>" (component (;1;) (type 2)))
45+
(instance (;2;) (instantiate 1
46+
(with "foo:bar/baz" (instance 0))
47+
)
48+
)
49+
(@producers
50+
(processed-by "wac-parser" "0.1.0")
51+
)
52+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(component
2+
(import "foo:bar/baz" (instance
3+
(type (record (field "x" u32)))
4+
(export "x" (type (eq 0)))
5+
(export "y" (func (param "x" 1)))
6+
))
7+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(component
2+
(import "foo:bar/baz" (instance
3+
(type (record (field "x" u32)))
4+
(export "x" (type (eq 0)))
5+
(export "z" (func (param "x" 1)))
6+
))
7+
)

0 commit comments

Comments
 (0)