Search Unity

IL2CPP max nested generic types

Discussion in 'Scripting' started by BCook99, Jul 14, 2018.

  1. BCook99

    BCook99

    Joined:
    Feb 17, 2015
    Posts:
    16
    I am getting this error using 2018.1.7f in my IL2CPP windows standalone build:

    The error seems to occur somewhere around 10 levels of nested types. We use deep nested generic types as part of our AI scripting system and sometimes need to go 15-20 levels deep.

    The code works perfectly well on regular Mono backend.

    My question is, why is there an arbitrary nesting limit imposed by IL2CPP? It seems to me this is a bug. The behavior is not documented anywhere. If it is simply a hardcoded constant limit then I'd like to request it be raised much higher, say 50.
     
    BowlingPin likes this.
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Wouldn't harm to file a bug report.

    Though 15-20 levels is fairly deep nesting. :D
     
  3. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    This limit is a trade-off between compile time/code size and run time usage of that code. Since IL2CPP is an ahead-of-time compiler, it need to generate all of the code at compile time. Mono's JIT only generates code for what is executed. Mono's AOT code generation engine as a similar issue.

    During code generation, IL2CPP needs to stop infinitely nested generic types somewhere, otherwise it could go on generating code until it runs out of memory. So we do limit the nested generic code generation to seven levels. This is a value we came up with through study of a number of projects. It's not documented because it is not an option which can be modified by users, unfortunately.

    If you'd like to file a bug report, we'll be happy to look at your project. We might consider making this an option that is user-controlled. In our experience though, at nesting level of 50 will make you build times really long.
     
    lordofduct and Joe-Censored like this.
  4. andreasvh

    andreasvh

    Joined:
    Sep 26, 2018
    Posts:
    3
    It seems to me that this at the very least should be documented as part of the scripting restrictions. Even if I can't change the value (which would also be a nice feature), I still want somewhere to read about why it is there and what I need to do if I run into it.

    Currently running into this issue is quite frustrating. This forum post seems to be the only information available about this issue anywhere. But it still leaves a lot of questions. How do you count the nesting level? Is Func3<int, int, int> 2, 3, or 4 or something else? Do we have to keep it <7 or <=7? Could we get around this by strategically casting nested types to and from object? Or does the actual nesting level stay the same even if I cast to object? Figuring out exactly what part of the code causes the problem without knowledge of the intricacies of the C# compiler and IL2CPP seems difficult to me. I don't really have a mental image of what instances of generic functions would have to be generated for the code I write. This is one of the things I count on the compiler for.

    Furthermore trial and error is frustrating because the only way I can find to test is to build for iOS and actually run the code on an iPad, which takes several minutes each time.

    I guess that if this was easy it could be done statically at compile time, so I don't expect it to be easy. But with some documentation giving a bit more details than the number 7, at least I wouldn't have to try and fix this blindly.

    Alternatively being able to configure this number in the project settings would make fixing these issues easy at the cost of increased build times.
     
    Last edited: Feb 18, 2019
  5. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    It does make sense to document this restriction. I'll update the documentation.

    The nesting level is computed for generic types and arrays. So Func3<int, int, int> has a nesting level of 1. A type like List<Fun3<int, int int>> has a nesting level of 2. And a type like List<Fun3<int, int int>>[] (an array of lists) has a nesting level of 3.

    The nesting level should be allowed equal to 7, but not more.

    I don't believe that casting to object will help, because the actual implementation of the generic type at that nesting level needs to exist.

    It feels like our error reporting is falling short if this is the case. There should be a clear managed exception which indicates the type that caused the problem and shows the call stack when this occurs at runtime. Can you provide an example of the exception you see? Maybe we can improve this.

    This is an option we have considered in the past. I'd like to make sure are error reporting is appropriate first though.
     
    Peter77 likes this.
  6. Walkramis

    Walkramis

    Joined:
    Jul 4, 2018
    Posts:
    2
    Hi,

    I am having a similar issue to this and wonder if there are any updates on configuring the number of nested generics?
    Thanks in advance!
     
  7. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Unfortunately we have not yet exposed an option to configure the number of nested generic types.
     
  8. Walkramis

    Walkramis

    Joined:
    Jul 4, 2018
    Posts:
    2
    Thanks for the quick reply!
    Is there a plan to implement this on the roadmap, or somthing similar in the near future?
     
  9. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    We don't have a plan to implement this soon.
     
  10. RazaTech

    RazaTech

    Joined:
    Feb 27, 2015
    Posts:
    178
    Hello!!
    Can we change MaximumRecursiveGenericDepth now ? in unity 2020.1 ?
     
  11. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Bunny83 and RazaTech like this.
  12. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,166
  13. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    No, that GUI box will pass arguments to the C# compiler, but not to IL2CPP. We don't have a GUI for additional IL2CPP arguments.
     
    Thaina likes this.
  14. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,166
    Please have it, project wide config like this should be saved in project setting not the code
     
  15. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Good point, we will consider this.