Aleph-Alpha / ts-rs

Generate TypeScript bindings from Rust types
MIT License
989 stars 99 forks source link

TypeList recursion limit #289

Closed kamadorueda closed 3 months ago

kamadorueda commented 3 months ago

Describe the bug

Since the upgrade from 7.1.1 to 8.1.0, I'm getting recursion limit errors

error[E0275]: overflow evaluating the requirement `impl TypeList well-formed`

or

reached the recursion limit while instantiating `<(((((..., ...), ...), ...), ...), ...) as TypeList>::for_each::<...>`

(on a crate that depends on a crate with #![recursion_limit = "..."])

To Reproduce

Derive TS on an enum with 130+ fields, for example:

#[derive(Debug, ts_rs::TS)]
#[ts(export)]
pub enum Iso4217CurrencyCode {
    AED,
    AFN,
    ALL,
    AMD,
    ANG,
    AOA,
    ARS,
    AUD,
    AWG,
    AZN,
    BAM,
    BBD,
    BDT,
    BGN,
    BHD,
    BIF,
    BMD,
    BND,
    BOB,
    BRL,
    BSD,
    BTN,
    BWP,
    BYN,
    BZD,
    CAD,
    CDF,
    CHF,
    CLP,
    CNY,
    COP,
    CRC,
    CUC,
    CUP,
    CVE,
    CZK,
    DJF,
    DKK,
    DOP,
    DZD,
    EGP,
    ERN,
    ETB,
    EUR,
    FJD,
    FKP,
    GBP,
    GEL,
    GGP,
    GHS,
    GIP,
    GMD,
    GNF,
    GTQ,
    GYD,
    HKD,
    HNL,
    HRK,
    HTG,
    HUF,
    IDR,
    ILS,
    IMP,
    INR,
    IQD,
    IRR,
    ISK,
    JEP,
    JMD,
    JOD,
    JPY,
    KES,
    KGS,
    KHR,
    KMF,
    KPW,
    KRW,
    KWD,
    KYD,
    KZT,
    LAK,
    LBP,
    LKR,
    LRD,
    LSL,
    LYD,
    MAD,
    MDL,
    MGA,
    MKD,
    MMK,
    MNT,
    MOP,
    MRU,
    MUR,
    MVR,
    MWK,
    MXN,
    MYR,
    MZN,
    NAD,
    NGN,
    NIO,
    NOK,
    NPR,
    NZD,
    OMR,
    PAB,
    PEN,
    PGK,
    PHP,
    PKR,
    PLN,
    PYG,
    QAR,
    RON,
    RSD,
    RUB,
    RWF,
    SAR,
    SBD,
    SCR,
    SDG,
    SEK,
    SGD,
    SHP,
    SLL,
    SOS,
    SPL,
    // SRD,
    // STN,
    // SVC,
    // SYP,
    // SZL,
    // THB,
    // TJS,
    // TMT,
    // TND,
    // TOP,
    // TRY,
    // TTD,
    // TVD,
    // TWD,
    // TZS,
    // UAH,
    // UGX,
    USD,
    // UYU,
    // UZS,
    // VEF,
    // VND,
    // VUV,
    // WST,
    // XAF,
    // XCD,
    // XDR,
    // XOF,
    // XPF,
    // YER,
    // ZAR,
    // ZMW,
    // ZWD,
}

fn main() {
    println!("{:?}", Iso4217CurrencyCode::USD)
}

if you comment out some variants, it compiles. There is a point where it stops compiling (the default recursion limit is 128)

Expected behavior

Screenshots

Version 8.1.0

escritorio-gustavo commented 3 months ago

Interesting! Well this is going to be inevitable if your type actually has 128+ dependencies (somehow), but in your case, the function dependency_types is trying to build ((), ((), ((), ...))) with a whole lot of empty TypeLists inside of each other, I'll make a PR to fix that

NyxCode commented 3 months ago

:laughing: I thought we might be reach that limit at some point!

@escritorio-gustavo One way we could tackle this is by generating a custom TypeList, instead of returning e.g ((((((((((), Type1), Type2), ......)))))

fn dependency_types() -> impl TypeList {
  struct List;
  impl TypeList for List {
    fn for_each(self, v: &mut Visitor) {
      v.visit::<Type1>();
      v.visit::<Type2>();
      OtherType::depencency_types().for_each(v);
      ...
    }
  } 
  List
}
escritorio-gustavo commented 3 months ago

😆 I thought we might be reach that limit at some point!

@escritorio-gustavo One way we could tackle this is by generating a custom TypeList, instead of returning e.g ((((((((((), Type1), Type2), ......)))))

fn dependency_types() -> impl TypeList {
  struct List;
  impl TypeList for List {
    fn for_each(self, v: &mut Visitor) {
      v.visit::<Type1>();
      v.visit::<Type2>();
      OtherType::depencency_types().for_each(v);
      ...
    }
  } 
  List
}

Cool! That could be the way to fix the case for > 128 dependencies. The thing is... I barely understand the TypeList currently, so I have no clue how to do that 😅

dessalines commented 2 weeks ago

I'm getting this issue on the 8.0.0 release:

overflow evaluating the requirement impl ts_rs::typelist::TypeList well-formed

NyxCode commented 2 weeks ago

@dessalines The newly released 9.0.0 should fix this!

dessalines commented 2 weeks ago

Nice, thx!