@@ -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)`
22882288pub 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 ) ]
23102458pub enum CmPrimitiveType {
0 commit comments