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

ADT derivation limits #639

Closed
ghostbuster91 opened this issue Jan 19, 2024 · 2 comments
Closed

ADT derivation limits #639

ghostbuster91 opened this issue Jan 19, 2024 · 2 comments

Comments

@ghostbuster91
Copy link

ghostbuster91 commented Jan 19, 2024

Hi, recently in our project we encountered a bug with kittens derivation for a mid-size ADT that has 23 members (dangerously close to magical 24 number).

Given the following code:

import cats.Eq
import cats.derived.*
import cats.syntax.all._

enum MyADT derives Eq {
  case A1
  case A2
  case A3
  case A4
  case A5
  case A6
  case A7
  case A8
  case A9
  case A10
  case A11
  case A12
  case A13
  case A14
  case A15
  case A16
  case A17
  case A18
  case A19
  case A20
  case A21
  case A22
  case AZ(foo: String)
}

the project fails to compile with quite a lengthy error:

[error] Note: given instance mkCoproductInstances in object K0 was not considered because it was not imported with `import given`.
[error] enum MyADT derives Eq {

full error

scala-cli snippet here

I made a couple of tests and found some interesting corellations.

When deriving Show instances we can only have 23 cases (without any fields!).
But for Eq typeclass we can have 27 cases (again without any fields).

However, if we add some fields to any of the cases, then each declared field will decrease the amount of possible cases by one starting from 23. In the presented case above we have 23 cases with and one field which does not compile. 22 cases in that example passes the compilation. Adding yet another field to the same case decrease the amount of possible cases.

Below does also not compile:

enum MyADT derives Eq {
  case A1
  case A2
  case A3
  case A4
  case A5
  case A6
  case A7
  case A8
  case A9
  case A10
  case A11
  case A12
  case A13
  case A14
  case A15
  case A16
  case A17
  // case A18
  // case A19
  // case A20
  // case A21
  // case A22
  case AZ(foo: String, foo2: String, foo3: String, foo4: String, foo5: String)
}

It seems that it is not the overal amount of fields that matter, but the maximum amount in all cases.

Below is fine:

enum MyADT derives Eq {
  case A1(foo5: String)
  case A2(foo5: String)
  case A3(foo5: String)
  case A4(foo5: String)
  case A5
  case A6
  case A7
  case A8
  case A9
  case A10
  case A11
  case A12
  case A13
  case A14
  case A15
  case A16
  case A17
  // case A18
  // case A19
  // case A20
  // case A21
  // case A22
  case AZ(foo: String, foo2: String, foo3: String, foo4: String)
}

scala version: 3.3.1
kittens: 3.2.0

Workaround

A possible workaround is to break such hierarchy into multiple ones, so in our first example that could be:

enum MyADT derives Eq {
  case A1_10(v: MyADTA10)
  case A11
  case A12
  case A13
  case A14
  case A15
  case A16
  case A17
  case A18
  case A19
  case A20
  case A21
  case A22
  case A2Z(foo: String)
}

enum MyADTA10 derives Eq {
  case A1
  case A2
  case A3
  case A4
  case A5
  case A6
  case A7
  case A8
  case A9
  case A10
}

which is obviously not ideal but it works.

@joroKr21
Copy link
Member

Did you try increasing -Xmax-inlines? I fear that the error message is misleading.

@ghostbuster91
Copy link
Author

ghostbuster91 commented Jan 19, 2024

TBH I totally forgot about this parameter, turns out increasing it to 64 fixes the problem.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants