-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Tail recursive evaluation of conditional types #45711
Conversation
…antiation depth limit to 100
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 093f76a. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 093f76a. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 093f76a. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at 093f76a. You can monitor the build here. Update: The results are in! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice if we could kinda automatically do the "extract to an accumulator" thing you suggest in the OP, so people didn't need to write their conditionals with such structure in mind; but this seems good.
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
@ahejlsberg Here they are:Comparison Report - main..45711
System
Hosts
Scenarios
Developer Information: |
I can't tell how much of this in the noise, but the check time on material-ui does seem like it's taken a hit across all versions. |
@typescript-bot perf test this |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at a4224d6. You can monitor the build here. Update: The results are in! |
@ahejlsberg Here they are:Comparison Report - main..45711
System
Hosts
Scenarios
Developer Information: |
Changed the tail recursion logic to bypass caching since it is effectively just computing temporary results. There's still a slight slowdown in material-ui (<1%), but generally I think not caching in the tail recursion loop is the best approach. |
@ahejlsberg Thanks for this work! Using 4.4.3, I just hit the Because it is possible / even likely to hit this depth limit of 50 with tuple types and template literal types in 4.4, I'm wondering if it would be possible to backport the |
- TypeScript currently permits up to 1000 recursive loops. - See: microsoft/TypeScript#45711
In #45025 we increased the type instantiation depth limit from 50 to 500. We've subsequently seen multiple examples of stack overflows occurring during compilation of programs containing non-terminating types, particularly when the compiler is used in browser hosted environments (where, apparently, in some cases the call stack limit is lower than in Node.js). It is clear that 500 is too high of a limit, so in this PR we lower the maximum to 100.
There are legitimate cases where evaluation of recursive conditional types needs more than 100 iterations to complete. For that reason, this PR implements tail recursive evaluation of conditional types. Specifically, when a conditional type ends in another (or, through recursion, another instantiation of the same) conditional type, the compiler now performs type resolution in a loop that consumes no extra call stack. We permit evaluation of such types to loop 1000 times before we consider the type non-terminating and issue an error.
The following conditional type is tail recursive:
Previously, resolution of instantiations of this type would error for string literals containing more than 25 blanks. We now permit strings with up to 1000 blanks.
Conditional types that aren't tail recursive generally can be written in a tail recursive form by introducing an "accumulator". For example, this type, which extracts a union of the characters in a string, isn't tail recursive (because it recurs through a union type)
but this rewritten form is
Some additional examples of tail recursive conditional types:
The examples above previously would error in "Type instantiation is excessively deep and possibly infinite", but now succeed.