@@ -523,19 +523,19 @@ macro_rules! {macro_name} {{
523523 func_name : & str ,
524524 payload_type : Option < & Type > ,
525525 ) {
526- let payload_type = match payload_type {
527- // Rust requires one-impl-per-type, so any `id` here is transformed
528- // into its canonical representation using
529- // `get_representative_type`. This ensures that type aliases, uses,
530- // etc, all get canonicalized to the exact same ID regardless of
531- // type structure.
532- //
533- // Note that `get_representative_type` maps ids-to-ids which is 95%
534- // of what we want, but this additionally goes one layer further to
535- // see if the final id is actually itself a typedef, which would
536- // always be to a primitive, and then uses the primitive type
537- // instead of the typedef to canonicalize with other streams/futures
538- // using the primitive type.
526+ // Rust requires one-impl-per-type, so any `id` here is transformed
527+ // into its canonical representation using
528+ // `get_representative_type`. This ensures that type aliases, uses,
529+ // etc, all get canonicalized to the exact same ID regardless of
530+ // type structure. This canonical key is used for deduplication only.
531+ //
532+ // Note that `get_representative_type` maps ids-to-ids which is 95%
533+ // of what we want, but this additionally goes one layer further to
534+ // see if the final id is actually itself a typedef, which would
535+ // always be to a primitive, and then uses the primitive type
536+ // instead of the typedef to canonicalize with other streams/futures
537+ // using the primitive type.
538+ let canonical_payload = match payload_type {
539539 Some ( Type :: Id ( id) ) => {
540540 let id = self . r#gen . types . get_representative_type ( * id) ;
541541 match self . resolve . types [ id] . kind {
@@ -545,20 +545,39 @@ macro_rules! {macro_name} {{
545545 }
546546 other => other. copied ( ) ,
547547 } ;
548+ {
549+ let map = match payload_for {
550+ PayloadFor :: Future => & self . r#gen . future_payloads ,
551+ PayloadFor :: Stream => & self . r#gen . stream_payloads ,
552+ } ;
553+ if map. contains_key ( & canonical_payload) {
554+ return ;
555+ }
556+ }
557+
558+ // Use the original (non-canonicalized) type for generating the
559+ // type name and code. The canonical representative may belong to
560+ // an interface that hasn't been processed yet (when world import
561+ // order differs from WIT definition order), which would cause
562+ // `path_to_interface` to panic. Since structurally equal types
563+ // resolve to the same Rust type, it doesn't matter which alias
564+ // path we use in the generated `impl`.
565+ let payload_type = match payload_type {
566+ Some ( Type :: Id ( id) ) => match self . resolve . types [ * id] . kind {
567+ TypeDefKind :: Type ( t) => Some ( t) ,
568+ _ => Some ( Type :: Id ( * id) ) ,
569+ } ,
570+ other => other. copied ( ) ,
571+ } ;
548572 let payload_type = payload_type. as_ref ( ) ;
549573 let name = match payload_type {
550574 Some ( payload_type) => self . type_name_owned ( payload_type) ,
551575 None => "()" . into ( ) ,
552576 } ;
553- let map = match payload_for {
554- PayloadFor :: Future => & mut self . r#gen . future_payloads ,
555- PayloadFor :: Stream => & mut self . r#gen . stream_payloads ,
577+ let ordinal = match payload_for {
578+ PayloadFor :: Future => self . r#gen . future_payloads . len ( ) ,
579+ PayloadFor :: Stream => self . r#gen . stream_payloads . len ( ) ,
556580 } ;
557-
558- if map. contains_key ( & payload_type. copied ( ) ) {
559- return ;
560- }
561- let ordinal = map. len ( ) ;
562581 let async_support = self . r#gen . async_support_path ( ) ;
563582 let ( size, align) = if let Some ( payload_type) = payload_type {
564583 (
@@ -704,7 +723,7 @@ pub mod vtable{ordinal} {{
704723 PayloadFor :: Future => & mut self . r#gen . future_payloads ,
705724 PayloadFor :: Stream => & mut self . r#gen . stream_payloads ,
706725 } ;
707- map. insert ( payload_type . copied ( ) , code) ;
726+ map. insert ( canonical_payload , code) ;
708727 }
709728
710729 fn generate_guest_import ( & mut self , func : & Function , interface : Option < & WorldKey > ) {
0 commit comments