Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeList recursion limit #289

Closed
kamadorueda opened this issue Apr 2, 2024 · 6 comments · Fixed by #291
Closed

TypeList recursion limit #289

kamadorueda opened this issue Apr 2, 2024 · 6 comments · Fixed by #291
Labels
bug Something isn't working

Comments

@kamadorueda
Copy link
Contributor

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

@kamadorueda kamadorueda added the bug Something isn't working label Apr 2, 2024
@escritorio-gustavo
Copy link
Contributor

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
Copy link
Collaborator

NyxCode commented Apr 2, 2024

😆 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
Copy link
Contributor

😆 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
Copy link

dessalines commented Jun 15, 2024

I'm getting this issue on the 8.0.0 release:

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

@NyxCode
Copy link
Collaborator

NyxCode commented Jun 20, 2024

@dessalines The newly released 9.0.0 should fix this!

@dessalines
Copy link

Nice, thx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants