Skip to content

Commit 5694b95

Browse files
authored
Merge pull request #733 from wado-lang/claude/fix-wasi-cm-fixtures-py3z9
Fix WASI CM bindings: ErrorCode collision, future.read, Option/variant flat lowering
2 parents ec4527a + 40546b1 commit 5694b95

File tree

57 files changed

+5156
-877
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+5156
-877
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ adler = { version = "1" }
4646
toml = { version = "1", default-features = false, features = ["parse", "display", "serde"] }
4747
libc = { version = "0.2" }
4848

49+
4950
[profile.dev.package.wado-compiler]
5051
opt-level = 1
5152

wado-compiler/src/cm_abi.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,19 @@ pub fn layout_option_with_registry(
230230
inner: &Type,
231231
registry: &crate::component_model::WasiRegistry,
232232
) -> CmLayout {
233-
let payload_align = crate::component_model::cm_align_with_registry(inner, registry);
234-
let payload_size = crate::component_model::cm_size_with_registry(inner, registry);
233+
layout_option_with_registry_scoped(inner, registry, None)
234+
}
235+
236+
/// Package-scoped registry-aware layout for option<T>.
237+
pub fn layout_option_with_registry_scoped(
238+
inner: &Type,
239+
registry: &crate::component_model::WasiRegistry,
240+
wasi_package: Option<&str>,
241+
) -> CmLayout {
242+
let payload_align =
243+
crate::component_model::cm_align_with_registry_scoped(inner, registry, wasi_package);
244+
let payload_size =
245+
crate::component_model::cm_size_with_registry_scoped(inner, registry, wasi_package);
235246
let overall_align = 1u32.max(payload_align);
236247
let payload_offset = align_to(1, payload_align);
237248
let size = align_to(payload_offset + payload_size, overall_align);
@@ -248,11 +259,24 @@ pub fn layout_result_with_registry(
248259
err: &Type,
249260
registry: &crate::component_model::WasiRegistry,
250261
) -> CmLayout {
251-
let payload_align = crate::component_model::cm_align_with_registry(ok, registry).max(
252-
crate::component_model::cm_align_with_registry(err, registry),
253-
);
254-
let payload_size = crate::component_model::cm_size_with_registry(ok, registry)
255-
.max(crate::component_model::cm_size_with_registry(err, registry));
262+
layout_result_with_registry_scoped(ok, err, registry, None)
263+
}
264+
265+
/// Package-scoped registry-aware layout for result<T, E>.
266+
pub fn layout_result_with_registry_scoped(
267+
ok: &Type,
268+
err: &Type,
269+
registry: &crate::component_model::WasiRegistry,
270+
wasi_package: Option<&str>,
271+
) -> CmLayout {
272+
let payload_align =
273+
crate::component_model::cm_align_with_registry_scoped(ok, registry, wasi_package).max(
274+
crate::component_model::cm_align_with_registry_scoped(err, registry, wasi_package),
275+
);
276+
let payload_size =
277+
crate::component_model::cm_size_with_registry_scoped(ok, registry, wasi_package).max(
278+
crate::component_model::cm_size_with_registry_scoped(err, registry, wasi_package),
279+
);
256280
let overall_align = 1u32.max(payload_align);
257281
let disc_size = 1u32;
258282
let payload_offset = align_to(disc_size, payload_align);

wado-compiler/src/codegen/component.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,7 @@ fn generate_wasi_imports(
14371437
.iter()
14381438
.filter(|name| {
14391439
project.wasi_registry.is_variant(name)
1440-
&& !(name.as_str() == "ErrorCode" && !has_local_error_code)
1440+
&& (name.as_str() != "ErrorCode" || has_local_error_code)
14411441
})
14421442
.cloned()
14431443
.collect();
@@ -1448,7 +1448,7 @@ fn generate_wasi_imports(
14481448
.filter(|name| {
14491449
project.wasi_registry.is_enum(name)
14501450
&& !needed_variants.contains(name)
1451-
&& !(name.as_str() == "ErrorCode" && !has_local_error_code)
1451+
&& (name.as_str() != "ErrorCode" || has_local_error_code)
14521452
})
14531453
.cloned()
14541454
.collect();

wado-compiler/src/component_model.rs

Lines changed: 151 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,16 +2286,37 @@ pub fn cm_align_with_registry(ty: &Type, registry: &WasiRegistry) -> u32 {
22862286
/// - payload: at `align_to(1, max_payload_align)`
22872287
/// - total: `align_to(payload_offset + max_payload_size, max_payload_align)`
22882288
pub fn wasi_variant_cm_size_align(name: &str, registry: &WasiRegistry) -> Option<(u32, u32)> {
2289-
let cases = registry.get_variant_cases(name)?;
2289+
wasi_variant_cm_size_align_scoped(name, registry, None)
2290+
}
2291+
2292+
/// Package-scoped variant of `wasi_variant_cm_size_align`.
2293+
///
2294+
/// When `wasi_package` is provided (e.g., `"http"`), uses package-scoped lookup
2295+
/// to disambiguate variant types that share the same Wado name across different
2296+
/// WASI packages (e.g., `ErrorCode` exists in http, filesystem, and sockets).
2297+
pub fn wasi_variant_cm_size_align_scoped(
2298+
name: &str,
2299+
registry: &WasiRegistry,
2300+
wasi_package: Option<&str>,
2301+
) -> Option<(u32, u32)> {
2302+
let cases = if let Some(pkg) = wasi_package {
2303+
registry
2304+
.get_variant_cases_by_package(pkg, name)
2305+
.or_else(|| registry.get_variant_cases(name))
2306+
} else {
2307+
registry.get_variant_cases(name)
2308+
}?;
22902309
if !cases.iter().any(|case| case.payload.is_some()) {
22912310
return None; // no payload cases — not outptr
22922311
}
22932312
let mut max_payload_size = 0u32;
22942313
let mut max_payload_align = 1u32;
22952314
for case in cases {
22962315
if let Some(ty) = &case.payload {
2297-
max_payload_size = max_payload_size.max(cm_size_with_registry(ty, registry));
2298-
max_payload_align = max_payload_align.max(cm_align_with_registry(ty, registry));
2316+
max_payload_size =
2317+
max_payload_size.max(cm_size_with_registry_scoped(ty, registry, wasi_package));
2318+
max_payload_align =
2319+
max_payload_align.max(cm_align_with_registry_scoped(ty, registry, wasi_package));
22992320
}
23002321
}
23012322
let disc_size = 1u32; // u8 for n ≤ 256 cases
@@ -2305,6 +2326,133 @@ pub fn wasi_variant_cm_size_align(name: &str, registry: &WasiRegistry) -> Option
23052326
Some((size, overall_align))
23062327
}
23072328

2329+
/// Package-scoped CM canonical ABI size for a type.
2330+
///
2331+
/// Like `cm_size_with_registry`, but uses `wasi_package` to disambiguate types
2332+
/// with the same name across different WASI packages.
2333+
pub fn cm_size_with_registry_scoped(
2334+
ty: &Type,
2335+
registry: &WasiRegistry,
2336+
wasi_package: Option<&str>,
2337+
) -> u32 {
2338+
match ty {
2339+
Type::Named(named) => {
2340+
if let Some(resolved) = registry.get_newtype(&named.name) {
2341+
return cm_size_with_registry_scoped(resolved, registry, wasi_package);
2342+
}
2343+
if let Some(fields) = registry.get_struct_fields(&named.name) {
2344+
let resolved_fields: Vec<Type> = fields
2345+
.iter()
2346+
.map(|(_, ty)| registry.resolve_type(ty))
2347+
.collect();
2348+
let mut offset = 0u32;
2349+
let mut max_align = 1u32;
2350+
for field_ty in &resolved_fields {
2351+
let fa = cm_align_with_registry_scoped(field_ty, registry, wasi_package);
2352+
let fs = cm_size_with_registry_scoped(field_ty, registry, wasi_package);
2353+
offset = crate::cm_abi::align_to(offset, fa);
2354+
offset += fs;
2355+
max_align = max_align.max(fa);
2356+
}
2357+
return crate::cm_abi::align_to(offset, max_align);
2358+
}
2359+
if let Some(sa) = wasi_variant_cm_size_align_scoped(&named.name, registry, wasi_package)
2360+
{
2361+
return sa.0;
2362+
}
2363+
if let Some(variants) = registry.get_enum_variants(&named.name) {
2364+
return crate::synthesis::cm_binding::cm_enum_byte_size(variants.len());
2365+
}
2366+
if let Some(members) = registry.get_flags_members(&named.name) {
2367+
return crate::synthesis::cm_binding::cm_flags_byte_size(members.len());
2368+
}
2369+
crate::cm_abi::cm_size(ty)
2370+
}
2371+
Type::Generic(g) => match g.name.as_str() {
2372+
"Option" if g.args.len() == 1 => {
2373+
let inner = &g.args[0];
2374+
let payload_align = cm_align_with_registry_scoped(inner, registry, wasi_package);
2375+
let payload_size = cm_size_with_registry_scoped(inner, registry, wasi_package);
2376+
let payload_offset = crate::cm_abi::align_to(1, payload_align);
2377+
let overall_align = 1u32.max(payload_align);
2378+
crate::cm_abi::align_to(payload_offset + payload_size, overall_align)
2379+
}
2380+
"Result" if g.args.len() == 2 => {
2381+
let ok_size = cm_size_with_registry_scoped(&g.args[0], registry, wasi_package);
2382+
let err_size = cm_size_with_registry_scoped(&g.args[1], registry, wasi_package);
2383+
let payload_size = ok_size.max(err_size);
2384+
let payload_align =
2385+
cm_align_with_registry_scoped(&g.args[0], registry, wasi_package).max(
2386+
cm_align_with_registry_scoped(&g.args[1], registry, wasi_package),
2387+
);
2388+
let payload_offset = crate::cm_abi::align_to(1, payload_align);
2389+
let overall_align = 1u32.max(payload_align);
2390+
crate::cm_abi::align_to(payload_offset + payload_size, overall_align)
2391+
}
2392+
_ => crate::cm_abi::cm_size(ty),
2393+
},
2394+
_ => crate::cm_abi::cm_size(ty),
2395+
}
2396+
}
2397+
2398+
/// Package-scoped CM canonical ABI alignment for a type.
2399+
pub fn cm_align_with_registry_scoped(
2400+
ty: &Type,
2401+
registry: &WasiRegistry,
2402+
wasi_package: Option<&str>,
2403+
) -> u32 {
2404+
match ty {
2405+
Type::Named(named) => {
2406+
if let Some(resolved) = registry.get_newtype(&named.name) {
2407+
return cm_align_with_registry_scoped(resolved, registry, wasi_package);
2408+
}
2409+
if let Some(fields) = registry.get_struct_fields(&named.name) {
2410+
let mut max_align = 1u32;
2411+
for (_, field_ty) in fields {
2412+
let resolved = registry.resolve_type(field_ty);
2413+
max_align = max_align.max(cm_align_with_registry_scoped(
2414+
&resolved,
2415+
registry,
2416+
wasi_package,
2417+
));
2418+
}
2419+
return max_align;
2420+
}
2421+
if let Some(sa) = wasi_variant_cm_size_align_scoped(&named.name, registry, wasi_package)
2422+
{
2423+
return sa.1;
2424+
}
2425+
if let Some(variants) = registry.get_enum_variants(&named.name) {
2426+
return crate::synthesis::cm_binding::cm_enum_byte_size(variants.len());
2427+
}
2428+
if let Some(members) = registry.get_flags_members(&named.name) {
2429+
return crate::synthesis::cm_binding::cm_flags_byte_align(members.len());
2430+
}
2431+
crate::cm_abi::cm_align(ty)
2432+
}
2433+
Type::Generic(g) => match g.name.as_str() {
2434+
"Option" if g.args.len() == 1 => 1u32.max(cm_align_with_registry_scoped(
2435+
&g.args[0],
2436+
registry,
2437+
wasi_package,
2438+
)),
2439+
"Result" if g.args.len() == 2 => 1u32
2440+
.max(cm_align_with_registry_scoped(
2441+
&g.args[0],
2442+
registry,
2443+
wasi_package,
2444+
))
2445+
.max(cm_align_with_registry_scoped(
2446+
&g.args[1],
2447+
registry,
2448+
wasi_package,
2449+
)),
2450+
_ => crate::cm_abi::cm_align(ty),
2451+
},
2452+
_ => crate::cm_abi::cm_align(ty),
2453+
}
2454+
}
2455+
23082456
/// Primitive type for CM tuple return handling
23092457
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23102458
pub enum CmPrimitiveType {

wado-compiler/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ pub async fn compile_with_options<H: CompilerHost>(
230230
let is_todo_module = load_result.entry_ast.has_todo();
231231

232232
// Wrap all subsequent Bail errors with is_todo_module
233-
let result = compile_after_load(load_result, options, &logger, filename).await;
233+
let result = compile_after_load(load_result, options, &logger, filename);
234234
match result {
235235
Ok((wasm, module, wir_module)) => Ok(CompileResult {
236236
wasm,
@@ -243,7 +243,7 @@ pub async fn compile_with_options<H: CompilerHost>(
243243
}
244244

245245
/// Internal: run compilation phases after module loading.
246-
async fn compile_after_load<H: CompilerHost>(
246+
fn compile_after_load<H: CompilerHost>(
247247
load_result: loader::LoadResult,
248248
options: CompilerOptions,
249249
logger: &Logger<'_, H>,

wado-compiler/src/monomorphize/func_inst.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ impl Monomorphizer {
19741974
// selects the correct generic function template
19751975
// ("&^IntoIterator::into_iter" instead of "Array^IntoIterator::into_iter").
19761976
if info.is_ref_impl {
1977-
new_info.base_struct_name = info.base_struct_name.clone();
1977+
new_info.base_struct_name.clone_from(&info.base_struct_name);
19781978
}
19791979
new_info
19801980
} else {

0 commit comments

Comments
 (0)