Skip to content
Open
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
15 changes: 15 additions & 0 deletions crates/core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ impl Types {
}
}
}

// Merge TypeInfo for structurally equal types so that all members
// of an equivalence class carry the union of all usage flags
// (borrowed, owned, etc.).
let mut merged: HashMap<TypeId, TypeInfo> = HashMap::new();
for (&id, &info) in &self.type_info {
let rep = self.equal_types.find(id);
*merged.entry(rep).or_default() |= info;
}
for (&id, info) in &mut self.type_info {
let rep = self.equal_types.find(id);
if let Some(&merged_info) = merged.get(&rep) {
*info = merged_info;
}
}
}

fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) {
Expand Down
48 changes: 48 additions & 0 deletions crates/rust/tests/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,54 @@ mod newtyped_list {
}
}
}

#[test]
fn merge_structurally_equal_types() {
let wit = r#"
package test:merge-equal;

interface importer {
record payload {
data: list<u8>,
tag: string,
}
consume: func(p: payload);
}

interface exporter {
record payload {
data: list<u8>,
tag: string,
}
produce: func() -> payload;
}

world test {
import importer;
export exporter;
}
"#;

let mut resolve = wit_bindgen_core::wit_parser::Resolve::default();
let pkg = resolve.push_str("test.wit", wit).unwrap();
let world = resolve.select_world(&[pkg], None).unwrap();

let opts = wit_bindgen_rust::Opts {
generate_all: true,
merge_structurally_equal_types: Some(Some(true)),
ownership: wit_bindgen_rust::Ownership::Borrowing {
duplicate_if_necessary: true,
},
..Default::default()
};

let mut generator = opts.build();
let mut files = wit_bindgen_core::Files::default();
// Should not panic and should generate valid code with merged types
use wit_bindgen_core::WorldGenerator;
generator.generate(&mut resolve, world, &mut files).unwrap();
}

#[allow(unused, reason = "testing codegen, not functionality")]
mod retyped_list {
use std::ops::Deref;
Expand Down
Loading