Fix calculation of param/result types in wit-bindgen (#5622)

This commit fixes a bug in the `bindgen!` macro for components where
previously the `param` and `result` properties weren't properly
calculated depending on the structure of the type and which types were
visited in which order. This is simplified to use a `LiveTypes`
structure from the `wit-parser` crate and relies on that to do necessary
recursion.
This commit is contained in:
Alex Crichton
2023-01-23 13:05:53 -06:00
committed by GitHub
parent ae441c50b6
commit 293005bd64
2 changed files with 41 additions and 87 deletions

View File

@@ -0,0 +1,15 @@
interface wasi-filesystem {
record descriptor-stat {
}
enum errno { e }
create-directory-at: func() -> result<_, errno>
stat: func() -> result<descriptor-stat, errno>
}
default world wasi {
import wasi-filesystem: self.wasi-filesystem
}

View File

@@ -54,25 +54,35 @@ impl Types {
}
fn type_info_func(&mut self, resolve: &Resolve, func: &Function) {
let mut live = LiveTypes::default();
for (_, ty) in func.params.iter() {
self.set_param_result_ty(
resolve,
ty,
TypeInfo {
param: true,
..TypeInfo::default()
},
);
self.type_info(resolve, ty);
live.add_type(resolve, ty);
}
for id in live.iter() {
self.type_info.get_mut(&id).unwrap().param = true;
}
let mut live = LiveTypes::default();
for ty in func.results.iter_types() {
self.set_param_result_ty(
resolve,
ty,
TypeInfo {
result: true,
..TypeInfo::default()
},
);
self.type_info(resolve, ty);
live.add_type(resolve, ty);
}
for id in live.iter() {
self.type_info.get_mut(&id).unwrap().result = true;
}
for ty in func.results.iter_types() {
let id = match ty {
Type::Id(id) => *id,
_ => continue,
};
let err = match &resolve.types[id].kind {
TypeDefKind::Result(Result_ { err, .. }) => err,
_ => continue,
};
if let Some(Type::Id(id)) = err {
self.type_info.get_mut(&id).unwrap().error = true;
}
}
}
@@ -151,75 +161,4 @@ impl Types {
None => TypeInfo::default(),
}
}
fn set_param_result_id(&mut self, resolve: &Resolve, ty: TypeId, info: TypeInfo) {
match &resolve.types[ty].kind {
TypeDefKind::Record(r) => {
for field in r.fields.iter() {
self.set_param_result_ty(resolve, &field.ty, info)
}
}
TypeDefKind::Tuple(t) => {
for ty in t.types.iter() {
self.set_param_result_ty(resolve, ty, info)
}
}
TypeDefKind::Flags(_) => {}
TypeDefKind::Enum(_) => {}
TypeDefKind::Variant(v) => {
for case in v.cases.iter() {
self.set_param_result_optional_ty(resolve, case.ty.as_ref(), info)
}
}
TypeDefKind::List(ty) | TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => {
self.set_param_result_ty(resolve, ty, info)
}
TypeDefKind::Result(r) => {
self.set_param_result_optional_ty(resolve, r.ok.as_ref(), info);
let mut info2 = info;
info2.error = info.result;
self.set_param_result_optional_ty(resolve, r.err.as_ref(), info2);
}
TypeDefKind::Union(u) => {
for case in u.cases.iter() {
self.set_param_result_ty(resolve, &case.ty, info)
}
}
TypeDefKind::Future(ty) => {
self.set_param_result_optional_ty(resolve, ty.as_ref(), info)
}
TypeDefKind::Stream(stream) => {
self.set_param_result_optional_ty(resolve, stream.element.as_ref(), info);
self.set_param_result_optional_ty(resolve, stream.end.as_ref(), info);
}
TypeDefKind::Unknown => unreachable!(),
}
}
fn set_param_result_ty(&mut self, resolve: &Resolve, ty: &Type, info: TypeInfo) {
match ty {
Type::Id(id) => {
self.type_id_info(resolve, *id);
let cur = self.type_info.get_mut(id).unwrap();
let prev = *cur;
*cur |= info;
if prev != *cur {
self.set_param_result_id(resolve, *id, info);
}
}
_ => {}
}
}
fn set_param_result_optional_ty(
&mut self,
resolve: &Resolve,
ty: Option<&Type>,
info: TypeInfo,
) {
match ty {
Some(ty) => self.set_param_result_ty(resolve, ty, info),
None => (),
}
}
}