components: Assert sizes match wit-parser sizes (#5943)
I was debugging [an issue] recently where it appears that the underlying cause was a discrepancy in the size/align of a WIT type between Wasmtime and `wit-parser`. This commit adds compile-time assertions that the size of a WIT type is the same with `wit-parser` as it is in Wasmtime since the two have different systems to calculate the size of a type. The hope is that this will head off any future issues if they crop up. [an issue]: https://github.com/bytecodealliance/wit-bindgen/issues/526
This commit is contained in:
@@ -32,6 +32,7 @@ struct Wasmtime {
|
|||||||
imports: Vec<Import>,
|
imports: Vec<Import>,
|
||||||
exports: Exports,
|
exports: Exports,
|
||||||
types: Types,
|
types: Types,
|
||||||
|
sizes: SizeAlign,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Import {
|
enum Import {
|
||||||
@@ -81,6 +82,7 @@ pub struct TrappableError {
|
|||||||
impl Opts {
|
impl Opts {
|
||||||
pub fn generate(&self, resolve: &Resolve, world: WorldId) -> String {
|
pub fn generate(&self, resolve: &Resolve, world: WorldId) -> String {
|
||||||
let mut r = Wasmtime::default();
|
let mut r = Wasmtime::default();
|
||||||
|
r.sizes.fill(resolve);
|
||||||
r.opts = self.clone();
|
r.opts = self.clone();
|
||||||
r.generate(resolve, world)
|
r.generate(resolve, world)
|
||||||
}
|
}
|
||||||
@@ -568,6 +570,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str(&name);
|
self.push_str(&name);
|
||||||
self.push_str("{}\n");
|
self.push_str("{}\n");
|
||||||
}
|
}
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,14 +587,15 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str(",");
|
self.push_str(",");
|
||||||
}
|
}
|
||||||
self.push_str(");\n");
|
self.push_str(");\n");
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_flags(&mut self, _id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
|
fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
|
||||||
self.rustdoc(docs);
|
self.rustdoc(docs);
|
||||||
|
let rust_name = to_rust_upper_camel_case(name);
|
||||||
self.src.push_str("wasmtime::component::flags!(\n");
|
self.src.push_str("wasmtime::component::flags!(\n");
|
||||||
self.src
|
self.src.push_str(&format!("{rust_name} {{\n"));
|
||||||
.push_str(&format!("{} {{\n", to_rust_upper_camel_case(name)));
|
|
||||||
for flag in flags.flags.iter() {
|
for flag in flags.flags.iter() {
|
||||||
// TODO wasmtime-component-macro doesnt support docs for flags rn
|
// TODO wasmtime-component-macro doesnt support docs for flags rn
|
||||||
uwrite!(
|
uwrite!(
|
||||||
@@ -603,6 +607,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
}
|
}
|
||||||
self.src.push_str("}\n");
|
self.src.push_str("}\n");
|
||||||
self.src.push_str(");\n\n");
|
self.src.push_str(");\n\n");
|
||||||
|
self.assert_type(id, &rust_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
|
fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
|
||||||
@@ -642,9 +647,27 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str("= Option<");
|
self.push_str("= Option<");
|
||||||
self.print_ty(payload, mode);
|
self.print_ty(payload, mode);
|
||||||
self.push_str(">;\n");
|
self.push_str(">;\n");
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit a double-check that the wit-parser-understood size of a type agrees
|
||||||
|
// with the Wasmtime-understood size of a type.
|
||||||
|
fn assert_type(&mut self, id: TypeId, name: &str) {
|
||||||
|
self.push_str("const _: () = {\n");
|
||||||
|
uwriteln!(
|
||||||
|
self.src,
|
||||||
|
"assert!({} == <{name} as wasmtime::component::ComponentType>::SIZE32);",
|
||||||
|
self.gen.sizes.size(&Type::Id(id)),
|
||||||
|
);
|
||||||
|
uwriteln!(
|
||||||
|
self.src,
|
||||||
|
"assert!({} == <{name} as wasmtime::component::ComponentType>::ALIGN32);",
|
||||||
|
self.gen.sizes.align(&Type::Id(id)),
|
||||||
|
);
|
||||||
|
self.push_str("};\n");
|
||||||
|
}
|
||||||
|
|
||||||
fn print_rust_enum<'b>(
|
fn print_rust_enum<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TypeId,
|
id: TypeId,
|
||||||
@@ -722,6 +745,8 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.print_generics(lt);
|
self.print_generics(lt);
|
||||||
self.push_str(" {}\n");
|
self.push_str(" {}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,6 +802,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str(",");
|
self.push_str(",");
|
||||||
self.print_optional_ty(result.err.as_ref(), mode);
|
self.print_optional_ty(result.err.as_ref(), mode);
|
||||||
self.push_str(">;\n");
|
self.push_str(">;\n");
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,6 +900,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
.map(|c| (c.name.to_upper_camel_case(), None)),
|
.map(|c| (c.name.to_upper_camel_case(), None)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
|
fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
|
||||||
@@ -886,6 +913,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str(" = ");
|
self.push_str(" = ");
|
||||||
self.print_ty(ty, mode);
|
self.print_ty(ty, mode);
|
||||||
self.push_str(";\n");
|
self.push_str(";\n");
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,6 +927,7 @@ impl<'a> InterfaceGenerator<'a> {
|
|||||||
self.push_str(" = ");
|
self.push_str(" = ");
|
||||||
self.print_list(ty, mode);
|
self.print_list(ty, mode);
|
||||||
self.push_str(";\n");
|
self.push_str(";\n");
|
||||||
|
self.assert_type(id, &name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user