Skip to content

Commit f941926

Browse files
committed
Fix wit-encoded exported interfaces with unused type aliases
Previously a panic would be hit during encoding since type type wasn't encoded. This commit updates to encode all named types unconditionally for exports to ensure this panic isn't hit. Along the way this also removes an unnecessary `index_primitive` method and map since during my prior refactorings in this code I found that it was necessary to implement the functionality deeper and forgot to come back and remove the original solution.
1 parent 5e5d63f commit f941926

File tree

4 files changed

+298
-95
lines changed

4 files changed

+298
-95
lines changed

crates/wit-component/src/encoding.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ impl<'a> InstanceTypeEncoder<'a> {
514514
struct TypeEncoder<'a> {
515515
types: ComponentTypeSection,
516516
type_map: IndexMap<TypeDefKey<'a>, u32>,
517-
primitive_map: IndexMap<PrimitiveValType, u32>,
518517
func_type_map: IndexMap<FunctionKey<'a>, u32>,
519518
exports: ComponentExportSection,
520519
}
@@ -602,21 +601,7 @@ impl<'a> TypeEncoder<'a> {
602601
_ => {}
603602
}
604603

605-
let mut exports = Vec::new();
606-
607-
for (id, def) in &import.types {
608-
let name = match &def.name {
609-
Some(name) => name,
610-
None => continue,
611-
};
612-
let idx = match self.encode_valtype(import, &Type::Id(id))? {
613-
// Named primitive types need entries in the type section, so
614-
// convert this to a type reference
615-
ComponentValType::Primitive(prim) => self.index_primitive(prim),
616-
ComponentValType::Type(idx) => idx,
617-
};
618-
exports.push((name.as_str(), ComponentTypeRef::Type(TypeBounds::Eq, idx)));
619-
}
604+
let mut exports = self.encode_interface_named_types(import)?;
620605

621606
for func in &import.functions {
622607
if let Some(required_funcs) = required_funcs {
@@ -633,6 +618,29 @@ impl<'a> TypeEncoder<'a> {
633618
Ok(Some(exports))
634619
}
635620

621+
fn encode_interface_named_types(
622+
&mut self,
623+
interface: &'a Interface,
624+
) -> Result<Vec<(&'a str, ComponentTypeRef)>> {
625+
let mut exports = Vec::new();
626+
627+
for (id, def) in &interface.types {
628+
let name = match &def.name {
629+
Some(name) => name,
630+
None => continue,
631+
};
632+
let idx = match self.encode_valtype(interface, &Type::Id(id))? {
633+
ComponentValType::Type(idx) => idx,
634+
// With a name this type should be converted to an indexed type
635+
// automatically and this shouldn't be possible.
636+
ComponentValType::Primitive(_) => unreachable!(),
637+
};
638+
exports.push((name.as_str(), ComponentTypeRef::Type(TypeBounds::Eq, idx)));
639+
}
640+
641+
Ok(exports)
642+
}
643+
636644
fn encode_func_types(&mut self, interfaces: impl Iterator<Item = &'a Interface>) -> Result<()> {
637645
for export in interfaces {
638646
// TODO: stick interface documentation in a custom section?
@@ -882,14 +890,6 @@ impl<'a> TypeEncoder<'a> {
882890
Ok(ComponentValType::Type(index))
883891
}
884892

885-
fn index_primitive(&mut self, ty: PrimitiveValType) -> u32 {
886-
*self.primitive_map.entry(ty).or_insert_with(|| {
887-
let index = self.types.len();
888-
self.types.defined_type().primitive(ty);
889-
index
890-
})
891-
}
892-
893893
fn validate_function(function: &Function) -> Result<()> {
894894
if function.name.is_empty() {
895895
bail!("interface has an unnamed function");
@@ -2327,6 +2327,10 @@ impl ComponentEncoder {
23272327
imports.adapters.insert(name, info);
23282328
}
23292329

2330+
for (interface, _default) in exports.clone() {
2331+
types.encode_interface_named_types(interface)?;
2332+
}
2333+
23302334
types.finish(&mut state.component);
23312335

23322336
state.encode_imports(&imports);

crates/wit-component/tests/interfaces/records/component.wat

Lines changed: 136 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,78 @@
11
(component
2-
(type (;0;) (record))
3-
(type (;1;) (record (field "a" u32) (field "b" u32)))
4-
(type (;2;) (flags "a" "b" "c" "d" "e" "f" "g" "h" "i"))
5-
(type (;3;) (record (field "a" 1) (field "b" u32) (field "c" 0) (field "d" string) (field "e" 2)))
6-
(type (;4;) s32)
7-
(type (;5;) (tuple 4))
8-
(type (;6;) (tuple char u32))
2+
(type (;0;) (tuple char u32))
3+
(type (;1;) (func (param "x" 0)))
4+
(type (;2;) (func (result 0)))
5+
(type (;3;) (record))
6+
(type (;4;) (func (param "x" 3)))
7+
(type (;5;) (func (result 3)))
8+
(type (;6;) (record (field "a" u32) (field "b" u32)))
99
(type (;7;) (func (param "x" 6)))
1010
(type (;8;) (func (result 6)))
11-
(type (;9;) (func (param "x" 0)))
12-
(type (;10;) (func (result 0)))
13-
(type (;11;) (func (param "x" 1)))
14-
(type (;12;) (func (result 1)))
15-
(type (;13;) (func (param "x" 2)))
16-
(type (;14;) (func (result 2)))
17-
(type (;15;) (func (param "x" 3)))
18-
(type (;16;) (func (result 3)))
19-
(type (;17;) (func (param "e" 5) (result s32)))
20-
(type (;18;)
11+
(type (;9;) (record (field "a" bool) (field "b" bool) (field "c" bool) (field "d" bool) (field "e" bool) (field "f" bool) (field "g" bool) (field "h" bool) (field "i" bool)))
12+
(type (;10;) (func (param "x" 9)))
13+
(type (;11;) (func (result 9)))
14+
(type (;12;) (record (field "a" 6) (field "b" u32) (field "c" 3) (field "d" string) (field "e" 9)))
15+
(type (;13;) (func (param "x" 12)))
16+
(type (;14;) (func (result 12)))
17+
(type (;15;) s32)
18+
(type (;16;) (tuple 15))
19+
(type (;17;) (func (param "e" 16) (result s32)))
20+
(type (;18;) (flags "a" "b" "c" "d" "e" "f" "g" "h" "i"))
21+
(type (;19;) (record (field "a" 6) (field "b" u32) (field "c" 3) (field "d" string) (field "e" 18)))
22+
(type (;20;) (func (param "x" 18)))
23+
(type (;21;) (func (result 18)))
24+
(type (;22;) (func (param "x" 19)))
25+
(type (;23;) (func (result 19)))
26+
(type (;24;)
2127
(instance
22-
(alias outer 1 0 (type (;0;)))
28+
(alias outer 1 3 (type (;0;)))
2329
(export "empty" (type (eq 0)))
24-
(alias outer 1 1 (type (;1;)))
30+
(alias outer 1 6 (type (;1;)))
2531
(export "scalars" (type (eq 1)))
26-
(alias outer 1 2 (type (;2;)))
32+
(alias outer 1 18 (type (;2;)))
2733
(export "really-flags" (type (eq 2)))
28-
(alias outer 1 3 (type (;3;)))
34+
(alias outer 1 19 (type (;3;)))
2935
(export "aggregates" (type (eq 3)))
30-
(alias outer 1 4 (type (;4;)))
36+
(alias outer 1 15 (type (;4;)))
3137
(export "int-typedef" (type (eq 4)))
32-
(alias outer 1 5 (type (;5;)))
38+
(alias outer 1 16 (type (;5;)))
3339
(export "tuple-typedef2" (type (eq 5)))
34-
(alias outer 1 7 (type (;6;)))
40+
(alias outer 1 1 (type (;6;)))
3541
(export "tuple-arg" (func (type 6)))
36-
(alias outer 1 8 (type (;7;)))
42+
(alias outer 1 2 (type (;7;)))
3743
(export "tuple-result" (func (type 7)))
38-
(alias outer 1 9 (type (;8;)))
44+
(alias outer 1 4 (type (;8;)))
3945
(export "empty-arg" (func (type 8)))
40-
(alias outer 1 10 (type (;9;)))
46+
(alias outer 1 5 (type (;9;)))
4147
(export "empty-result" (func (type 9)))
42-
(alias outer 1 11 (type (;10;)))
48+
(alias outer 1 7 (type (;10;)))
4349
(export "scalar-arg" (func (type 10)))
44-
(alias outer 1 12 (type (;11;)))
50+
(alias outer 1 8 (type (;11;)))
4551
(export "scalar-result" (func (type 11)))
46-
(alias outer 1 13 (type (;12;)))
52+
(alias outer 1 20 (type (;12;)))
4753
(export "flags-arg" (func (type 12)))
48-
(alias outer 1 14 (type (;13;)))
54+
(alias outer 1 21 (type (;13;)))
4955
(export "flags-result" (func (type 13)))
50-
(alias outer 1 15 (type (;14;)))
56+
(alias outer 1 22 (type (;14;)))
5157
(export "aggregate-arg" (func (type 14)))
52-
(alias outer 1 16 (type (;15;)))
58+
(alias outer 1 23 (type (;15;)))
5359
(export "aggregate-result" (func (type 15)))
5460
(alias outer 1 17 (type (;16;)))
5561
(export "typedef-inout" (func (type 16)))
5662
)
5763
)
58-
(import "records" (instance (;0;) (type 18)))
64+
(type (;25;) (tuple s32))
65+
(import "records" (instance (;0;) (type 24)))
5966
(core module (;0;)
6067
(type (;0;) (func (param i32 i32)))
6168
(type (;1;) (func (param i32)))
6269
(type (;2;) (func))
6370
(type (;3;) (func (result i32)))
6471
(type (;4;) (func (param i32 i32 i32 i32 i32 i32)))
6572
(type (;5;) (func (param i32) (result i32)))
66-
(type (;6;) (func (param i32 i32 i32 i32) (result i32)))
73+
(type (;6;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32)))
74+
(type (;7;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)))
75+
(type (;8;) (func (param i32 i32 i32 i32) (result i32)))
6776
(import "records" "tuple-arg" (func (;0;) (type 0)))
6877
(import "records" "tuple-result" (func (;1;) (type 1)))
6978
(import "records" "empty-arg" (func (;2;) (type 2)))
@@ -75,12 +84,58 @@
7584
(import "records" "aggregate-arg" (func (;8;) (type 4)))
7685
(import "records" "aggregate-result" (func (;9;) (type 1)))
7786
(import "records" "typedef-inout" (func (;10;) (type 5)))
78-
(func (;11;) (type 6) (param i32 i32 i32 i32) (result i32)
87+
(func (;11;) (type 0) (param i32 i32)
88+
unreachable
89+
)
90+
(func (;12;) (type 3) (result i32)
91+
unreachable
92+
)
93+
(func (;13;) (type 2)
94+
unreachable
95+
)
96+
(func (;14;) (type 2)
97+
unreachable
98+
)
99+
(func (;15;) (type 0) (param i32 i32)
100+
unreachable
101+
)
102+
(func (;16;) (type 3) (result i32)
103+
unreachable
104+
)
105+
(func (;17;) (type 6) (param i32 i32 i32 i32 i32 i32 i32 i32 i32)
106+
unreachable
107+
)
108+
(func (;18;) (type 3) (result i32)
109+
unreachable
110+
)
111+
(func (;19;) (type 7) (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)
112+
unreachable
113+
)
114+
(func (;20;) (type 3) (result i32)
115+
unreachable
116+
)
117+
(func (;21;) (type 1) (param i32))
118+
(func (;22;) (type 5) (param i32) (result i32)
119+
unreachable
120+
)
121+
(func (;23;) (type 8) (param i32 i32 i32 i32) (result i32)
79122
unreachable
80123
)
81124
(memory (;0;) 0)
125+
(export "records#tuple-arg" (func 11))
126+
(export "records#tuple-result" (func 12))
127+
(export "records#empty-arg" (func 13))
128+
(export "records#empty-result" (func 14))
129+
(export "records#scalar-arg" (func 15))
130+
(export "records#scalar-result" (func 16))
131+
(export "records#flags-arg" (func 17))
132+
(export "records#flags-result" (func 18))
133+
(export "records#aggregate-arg" (func 19))
134+
(export "records#aggregate-result" (func 20))
135+
(export "cabi_post_records#aggregate-result" (func 21))
136+
(export "records#typedef-inout" (func 22))
82137
(export "memory" (memory 0))
83-
(export "cabi_realloc" (func 11))
138+
(export "cabi_realloc" (func 23))
84139
)
85140
(core module (;1;)
86141
(type (;0;) (func (param i32)))
@@ -185,4 +240,48 @@
185240
(with "" (instance 3))
186241
)
187242
)
243+
(alias core export 2 "records#tuple-arg" (core func (;16;)))
244+
(func (;11;) (type 1) (canon lift (core func 16)))
245+
(alias core export 2 "records#tuple-result" (core func (;17;)))
246+
(func (;12;) (type 2) (canon lift (core func 17) (memory 0)))
247+
(alias core export 2 "records#empty-arg" (core func (;18;)))
248+
(func (;13;) (type 4) (canon lift (core func 18)))
249+
(alias core export 2 "records#empty-result" (core func (;19;)))
250+
(func (;14;) (type 5) (canon lift (core func 19)))
251+
(alias core export 2 "records#scalar-arg" (core func (;20;)))
252+
(func (;15;) (type 7) (canon lift (core func 20)))
253+
(alias core export 2 "records#scalar-result" (core func (;21;)))
254+
(func (;16;) (type 8) (canon lift (core func 21) (memory 0)))
255+
(alias core export 2 "records#flags-arg" (core func (;22;)))
256+
(func (;17;) (type 10) (canon lift (core func 22)))
257+
(alias core export 2 "records#flags-result" (core func (;23;)))
258+
(func (;18;) (type 11) (canon lift (core func 23) (memory 0)))
259+
(alias core export 2 "records#aggregate-arg" (core func (;24;)))
260+
(func (;19;) (type 13) (canon lift (core func 24) (memory 0) (realloc 11) string-encoding=utf8))
261+
(alias core export 2 "records#aggregate-result" (core func (;25;)))
262+
(alias core export 2 "cabi_post_records#aggregate-result" (core func (;26;)))
263+
(func (;20;) (type 14) (canon lift (core func 25) (memory 0) string-encoding=utf8 (post-return 26)))
264+
(alias core export 2 "records#typedef-inout" (core func (;27;)))
265+
(func (;21;) (type 17) (canon lift (core func 27)))
266+
(instance (;1;)
267+
(export "empty" (type 3))
268+
(export "scalars" (type 6))
269+
(export "really-flags" (type 9))
270+
(export "aggregates" (type 12))
271+
(export "tuple-typedef" (type 25))
272+
(export "int-typedef" (type 15))
273+
(export "tuple-typedef2" (type 16))
274+
(export "tuple-arg" (func 11))
275+
(export "tuple-result" (func 12))
276+
(export "empty-arg" (func 13))
277+
(export "empty-result" (func 14))
278+
(export "scalar-arg" (func 15))
279+
(export "scalar-result" (func 16))
280+
(export "flags-arg" (func 17))
281+
(export "flags-result" (func 18))
282+
(export "aggregate-arg" (func 19))
283+
(export "aggregate-result" (func 20))
284+
(export "typedef-inout" (func 21))
285+
)
286+
(export "records" (instance 1))
188287
)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
tuple-arg: func(x: tuple<char, u32>)
2+
tuple-result: func() -> tuple<char, u32>
3+
4+
record empty {}
5+
6+
empty-arg: func(x: empty)
7+
empty-result: func() -> empty
8+
9+
/// A record containing two scalar fields
10+
/// that both have the same type
11+
record scalars {
12+
/// The first field, named a
13+
a: u32,
14+
/// The second field, named b
15+
b: u32,
16+
}
17+
18+
scalar-arg: func(x: scalars)
19+
scalar-result: func() -> scalars
20+
21+
/// A record that is really just flags
22+
/// All of the fields are bool
23+
record really-flags {
24+
a: bool,
25+
b: bool,
26+
c: bool,
27+
d: bool,
28+
e: bool,
29+
f: bool,
30+
g: bool,
31+
h: bool,
32+
i: bool,
33+
}
34+
35+
flags-arg: func(x: really-flags)
36+
flags-result: func() -> really-flags
37+
38+
record aggregates {
39+
a: scalars,
40+
b: u32,
41+
c: empty,
42+
d: string,
43+
e: really-flags,
44+
}
45+
46+
aggregate-arg: func(x: aggregates)
47+
aggregate-result: func() -> aggregates
48+
49+
type tuple-typedef = tuple<s32>
50+
type int-typedef = s32
51+
type tuple-typedef2 = tuple<int-typedef>
52+
typedef-inout: func(e: tuple-typedef2) -> s32

0 commit comments

Comments
 (0)