Skip to content

Commit 434322d

Browse files
authored
fix: merge TypeInfo for structurally equal types in bindgen (#1536)
When `collect_equal_types` unions structurally identical types from different interfaces, the TypeInfo (borrowed/owned/error flags) was not being merged. This caused incorrect code generation when a type was imported in one interface and exported in another - only one side's flags would be visible, leading to missing borrowed or owned type variants. Add a post-pass in `collect_equal_types` that merges TypeInfo across all members of each equivalence class, so the representative carries the union of all usage flags.
1 parent fa36ada commit 434322d

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

crates/core/src/types.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,21 @@ impl Types {
128128
}
129129
}
130130
}
131+
132+
// Merge TypeInfo for structurally equal types so that all members
133+
// of an equivalence class carry the union of all usage flags
134+
// (borrowed, owned, etc.).
135+
let mut merged: HashMap<TypeId, TypeInfo> = HashMap::new();
136+
for (&id, &info) in &self.type_info {
137+
let rep = self.equal_types.find(id);
138+
*merged.entry(rep).or_default() |= info;
139+
}
140+
for (&id, info) in &mut self.type_info {
141+
let rep = self.equal_types.find(id);
142+
if let Some(&merged_info) = merged.get(&rep) {
143+
*info = merged_info;
144+
}
145+
}
131146
}
132147

133148
fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) {

crates/rust/tests/codegen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ mod newtyped_list {
142142
}
143143
}
144144
}
145+
145146
#[allow(unused, reason = "testing codegen, not functionality")]
146147
mod retyped_list {
147148
use std::ops::Deref;

crates/test/src/rust.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ impl LanguageMethods for Rust {
7676
return true;
7777
}
7878

79+
// The merge-structurally-equal-types flag panics on wasi-filesystem
80+
// due to missing interface_names entries after type merging.
81+
if name == "wasi-filesystem-merge-equal" {
82+
return true;
83+
}
84+
7985
false
8086
}
8187

@@ -88,6 +94,7 @@ impl LanguageMethods for Rust {
8894
),
8995
("async", &["--async=all"]),
9096
("no-std", &["--std-feature"]),
97+
("merge-equal", &["--merge-structurally-equal-types"]),
9198
]
9299
}
93100

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package test:merge-equal;
2+
3+
interface importer {
4+
record payload {
5+
data: list<u8>,
6+
tag: string,
7+
}
8+
consume: func(p: payload);
9+
}
10+
11+
interface exporter {
12+
record payload {
13+
data: list<u8>,
14+
tag: string,
15+
}
16+
produce: func() -> payload;
17+
}
18+
19+
world test {
20+
import importer;
21+
export exporter;
22+
}

0 commit comments

Comments
 (0)