Skip to content

Commit 18eb686

Browse files
authored
Fix using Rust types in owned and borrowed contexts (#514)
This pulls in type analysis code from Wasmtime which has a more modern notion of param/result as owned/borrowed and additionally removes the need for a `default_param_mode` which caused #513 in the first place. Closes #513
1 parent 4625271 commit 18eb686

File tree

7 files changed

+141
-208
lines changed

7 files changed

+141
-208
lines changed

crates/bindgen-core/src/lib.rs

Lines changed: 59 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ pub struct Types {
1616
#[derive(Default, Clone, Copy, Debug)]
1717
pub struct TypeInfo {
1818
/// Whether or not this type is ever used (transitively) within the
19-
/// parameter of a function.
20-
pub param: bool,
19+
/// parameter of an imported function.
20+
///
21+
/// This means that it's used in a context where ownership isn't
22+
/// relinquished.
23+
pub borrowed: bool,
2124

2225
/// Whether or not this type is ever used (transitively) within the
23-
/// result of a function.
24-
pub result: bool,
26+
/// parameter or result of an export, or the result of an import.
27+
///
28+
/// This means that it's used in a context where ownership is required and
29+
/// memory management is necessary.
30+
pub owned: bool,
2531

2632
/// Whether or not this type is ever used (transitively) within the
2733
/// error case in the result of a function.
@@ -33,8 +39,8 @@ pub struct TypeInfo {
3339

3440
impl std::ops::BitOrAssign for TypeInfo {
3541
fn bitor_assign(&mut self, rhs: Self) {
36-
self.param |= rhs.param;
37-
self.result |= rhs.result;
42+
self.borrowed |= rhs.borrowed;
43+
self.owned |= rhs.owned;
3844
self.error |= rhs.error;
3945
self.has_list |= rhs.has_list;
4046
}
@@ -45,29 +51,63 @@ impl Types {
4551
for (t, _) in resolve.types.iter() {
4652
self.type_id_info(resolve, t);
4753
}
48-
for (_, iface) in resolve.interfaces.iter() {
49-
for (_, f) in iface.functions.iter() {
50-
self.type_info_func(resolve, f);
51-
}
52-
}
5354
for (_, world) in resolve.worlds.iter() {
54-
for (_, item) in world.imports.iter().chain(&world.exports) {
55+
for (import, (_, item)) in world
56+
.imports
57+
.iter()
58+
.map(|i| (true, i))
59+
.chain(world.exports.iter().map(|i| (false, i)))
60+
{
5561
match item {
5662
WorldItem::Function(f) => {
57-
self.type_info_func(resolve, f);
63+
self.type_info_func(resolve, f, import);
5864
}
59-
WorldItem::Interface(_) | WorldItem::Type(_) => {}
65+
WorldItem::Interface(id) => {
66+
for (_, f) in resolve.interfaces[*id].functions.iter() {
67+
self.type_info_func(resolve, f, import);
68+
}
69+
}
70+
WorldItem::Type(_) => {}
6071
}
6172
}
6273
}
6374
}
6475

65-
fn type_info_func(&mut self, resolve: &Resolve, f: &Function) {
66-
for (_, ty) in f.params.iter() {
67-
self.set_param_result_ty(resolve, ty, true, false, false);
76+
fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) {
77+
let mut live = LiveTypes::default();
78+
for (_, ty) in func.params.iter() {
79+
self.type_info(resolve, ty);
80+
live.add_type(resolve, ty);
81+
}
82+
for id in live.iter() {
83+
let info = self.type_info.get_mut(&id).unwrap();
84+
if import {
85+
info.borrowed = true;
86+
} else {
87+
info.owned = true;
88+
}
6889
}
69-
for ty in f.results.iter_types() {
70-
self.set_param_result_ty(resolve, ty, false, true, false);
90+
let mut live = LiveTypes::default();
91+
for ty in func.results.iter_types() {
92+
self.type_info(resolve, ty);
93+
live.add_type(resolve, ty);
94+
}
95+
for id in live.iter() {
96+
self.type_info.get_mut(&id).unwrap().owned = true;
97+
}
98+
99+
for ty in func.results.iter_types() {
100+
let id = match ty {
101+
Type::Id(id) => *id,
102+
_ => continue,
103+
};
104+
let err = match &resolve.types[id].kind {
105+
TypeDefKind::Result(Result_ { err, .. }) => err,
106+
_ => continue,
107+
};
108+
if let Some(Type::Id(id)) = err {
109+
self.type_info.get_mut(&id).unwrap().error = true;
110+
}
71111
}
72112
}
73113

@@ -146,110 +186,6 @@ impl Types {
146186
None => TypeInfo::default(),
147187
}
148188
}
149-
150-
fn set_param_result_id(
151-
&mut self,
152-
resolve: &Resolve,
153-
ty: TypeId,
154-
param: bool,
155-
result: bool,
156-
error: bool,
157-
) {
158-
match &resolve.types[ty].kind {
159-
TypeDefKind::Record(r) => {
160-
for field in r.fields.iter() {
161-
self.set_param_result_ty(resolve, &field.ty, param, result, error)
162-
}
163-
}
164-
TypeDefKind::Tuple(t) => {
165-
for ty in t.types.iter() {
166-
self.set_param_result_ty(resolve, ty, param, result, error)
167-
}
168-
}
169-
TypeDefKind::Flags(_) => {}
170-
TypeDefKind::Enum(_) => {}
171-
TypeDefKind::Variant(v) => {
172-
for case in v.cases.iter() {
173-
self.set_param_result_optional_ty(
174-
resolve,
175-
case.ty.as_ref(),
176-
param,
177-
result,
178-
error,
179-
)
180-
}
181-
}
182-
TypeDefKind::List(ty) | TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => {
183-
self.set_param_result_ty(resolve, ty, param, result, error)
184-
}
185-
TypeDefKind::Result(r) => {
186-
self.set_param_result_optional_ty(resolve, r.ok.as_ref(), param, result, error);
187-
self.set_param_result_optional_ty(resolve, r.err.as_ref(), param, result, result);
188-
}
189-
TypeDefKind::Union(u) => {
190-
for case in u.cases.iter() {
191-
self.set_param_result_ty(resolve, &case.ty, param, result, error)
192-
}
193-
}
194-
TypeDefKind::Future(ty) => {
195-
self.set_param_result_optional_ty(resolve, ty.as_ref(), param, result, error)
196-
}
197-
TypeDefKind::Stream(stream) => {
198-
self.set_param_result_optional_ty(
199-
resolve,
200-
stream.element.as_ref(),
201-
param,
202-
result,
203-
error,
204-
);
205-
self.set_param_result_optional_ty(
206-
resolve,
207-
stream.end.as_ref(),
208-
param,
209-
result,
210-
error,
211-
);
212-
}
213-
TypeDefKind::Unknown => unreachable!(),
214-
}
215-
}
216-
217-
fn set_param_result_ty(
218-
&mut self,
219-
resolve: &Resolve,
220-
ty: &Type,
221-
param: bool,
222-
result: bool,
223-
error: bool,
224-
) {
225-
match ty {
226-
Type::Id(id) => {
227-
self.type_id_info(resolve, *id);
228-
let info = self.type_info.get_mut(id).unwrap();
229-
if (param && !info.param) || (result && !info.result) || (error && !info.error) {
230-
info.param = info.param || param;
231-
info.result = info.result || result;
232-
info.error = info.error || error;
233-
self.set_param_result_id(resolve, *id, param, result, error);
234-
}
235-
}
236-
_ => {}
237-
}
238-
}
239-
240-
fn set_param_result_optional_ty(
241-
&mut self,
242-
resolve: &Resolve,
243-
ty: Option<&Type>,
244-
param: bool,
245-
result: bool,
246-
error: bool,
247-
) {
248-
match ty {
249-
Some(ty) => self.set_param_result_ty(resolve, ty, param, result, error),
250-
None => (),
251-
}
252-
}
253189
}
254190

255191
#[derive(Default)]

crates/gen-guest-c/src/lib.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,21 +1115,7 @@ impl InterfaceGenerator<'_> {
11151115
let ty = &self.resolve.types[*id];
11161116
match &ty.name {
11171117
Some(name) => {
1118-
match ty.owner {
1119-
TypeOwner::Interface(owner) => {
1120-
self.src.print(
1121-
stype,
1122-
&self.gen.interface_names[&owner].to_snake_case(),
1123-
);
1124-
self.src.print(stype, "_");
1125-
}
1126-
TypeOwner::World(owner) => {
1127-
self.src
1128-
.print(stype, &self.resolve.worlds[owner].name.to_snake_case());
1129-
self.src.print(stype, "_");
1130-
}
1131-
TypeOwner::None => {}
1132-
}
1118+
self.print_owner_namespace(stype, *id);
11331119

11341120
self.src.print(stype, &name.to_snake_case());
11351121
self.src.print(stype, "_t");
@@ -1149,6 +1135,25 @@ impl InterfaceGenerator<'_> {
11491135
}
11501136
}
11511137

1138+
fn print_owner_namespace(&mut self, stype: SourceType, id: TypeId) {
1139+
let ty = &self.resolve.types[id];
1140+
match ty.owner {
1141+
TypeOwner::Interface(owner) => {
1142+
self.src
1143+
.print(stype, &self.gen.interface_names[&owner].to_snake_case());
1144+
self.src.print(stype, "_");
1145+
}
1146+
TypeOwner::World(owner) => {
1147+
self.src
1148+
.print(stype, &self.resolve.worlds[owner].name.to_snake_case());
1149+
self.src.print(stype, "_");
1150+
}
1151+
TypeOwner::None => {
1152+
self.print_namespace(stype);
1153+
}
1154+
}
1155+
}
1156+
11521157
fn print_ty_name(&mut self, stype: SourceType, ty: &Type) {
11531158
match ty {
11541159
Type::Bool => self.src.print(stype, "bool"),
@@ -1457,6 +1462,9 @@ impl InterfaceGenerator<'_> {
14571462
self.src.h_helpers(&self.gen.world.to_snake_case());
14581463
self.src.h_helpers("_");
14591464
}
1465+
Type::Id(id) => {
1466+
self.print_owner_namespace(SourceType::HHelpers, *id);
1467+
}
14601468
_ => {
14611469
self.print_namespace(SourceType::HHelpers);
14621470
}

crates/gen-guest-rust/src/lib.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ impl RustWasm {
8686
&'a mut self,
8787
wasm_import_module: Option<&'a str>,
8888
resolve: &'a Resolve,
89-
default_param_mode: TypeMode,
9089
in_import: bool,
9190
) -> InterfaceGenerator<'a> {
9291
let mut sizes = SizeAlign::default();
@@ -100,7 +99,6 @@ impl RustWasm {
10099
gen: self,
101100
sizes,
102101
resolve,
103-
default_param_mode,
104102
return_pointer_area_size: 0,
105103
return_pointer_area_align: 0,
106104
}
@@ -126,7 +124,7 @@ impl WorldGenerator for RustWasm {
126124
) {
127125
let prev = self.interface_names.insert(id, name.to_snake_case());
128126
assert!(prev.is_none());
129-
let mut gen = self.interface(Some(name), resolve, TypeMode::AllBorrowed("'a"), true);
127+
let mut gen = self.interface(Some(name), resolve, true);
130128
gen.current_interface = Some(id);
131129
gen.types(id);
132130

@@ -144,7 +142,7 @@ impl WorldGenerator for RustWasm {
144142
funcs: &[(&str, &Function)],
145143
_files: &mut Files,
146144
) {
147-
let mut gen = self.interface(Some("$root"), resolve, TypeMode::AllBorrowed("'a"), true);
145+
let mut gen = self.interface(Some("$root"), resolve, true);
148146

149147
for (_, func) in funcs {
150148
gen.generate_guest_import(func);
@@ -162,7 +160,7 @@ impl WorldGenerator for RustWasm {
162160
_files: &mut Files,
163161
) {
164162
self.interface_names.insert(id, name.to_snake_case());
165-
let mut gen = self.interface(None, resolve, TypeMode::Owned, false);
163+
let mut gen = self.interface(None, resolve, false);
166164
gen.current_interface = Some(id);
167165
gen.types(id);
168166
gen.generate_exports(name, Some(name), resolve.interfaces[id].functions.values());
@@ -177,7 +175,7 @@ impl WorldGenerator for RustWasm {
177175
_files: &mut Files,
178176
) {
179177
let name = &resolve.worlds[world].name;
180-
let mut gen = self.interface(None, resolve, TypeMode::Owned, false);
178+
let mut gen = self.interface(None, resolve, false);
181179
gen.generate_exports(name, None, funcs.iter().map(|f| f.1));
182180
let src = gen.finish();
183181
self.src.push_str(&src);
@@ -190,7 +188,7 @@ impl WorldGenerator for RustWasm {
190188
types: &[(&str, TypeId)],
191189
_files: &mut Files,
192190
) {
193-
let mut gen = self.interface(None, resolve, TypeMode::Owned, false);
191+
let mut gen = self.interface(None, resolve, false);
194192
for (name, ty) in types {
195193
gen.define_type(name, *ty);
196194
}
@@ -321,7 +319,6 @@ struct InterfaceGenerator<'a> {
321319
gen: &'a mut RustWasm,
322320
wasm_import_module: Option<&'a str>,
323321
resolve: &'a Resolve,
324-
default_param_mode: TypeMode,
325322
return_pointer_area_size: usize,
326323
return_pointer_area_align: usize,
327324
}
@@ -634,10 +631,6 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
634631
"wit_bindgen::rt::string::String"
635632
}
636633

637-
fn default_param_mode(&self) -> TypeMode {
638-
self.default_param_mode
639-
}
640-
641634
fn push_str(&mut self, s: &str) {
642635
self.src.push_str(s);
643636
}

0 commit comments

Comments
 (0)