Open Xunnamius opened 2 years ago
This seems to bisect to #49119.
Stumbled across this one and took a quick look. The core issue is that the types in the repo are very expensive to compute, as is evident by the painful slowness of intellisense in the example. For example, checking the visitAndReveal
function in the example causes ~5.8M type instantiations in 4.7 when compiled with tsc
. This shrinks to ~1.2M type instantiations in 4.8 and later. Those numbers are big warning flags that the types are too complex.
That said, we obviously shouldn't hang the language service and I'm not sure why that happens. The example compiles with tsc
with or without the commented out section, and I would expect the same from the language service.
Very odd that we hang in 4.8+ when those versions have the fewer instantiations; I would have assumed the opposite.
For example, checking the
visitAndReveal
function in the example causes ~5.8M type instantiations in 4.7 when compiled withtsc
. This shrinks to ~1.2M type instantiations in 4.8 and later. Those numbers are big warning flags that the types are too complex.
Thanks for taking a look! I had a suspicion complexity was a problem after some other small issues with the types coming from the unist-util-visit package. For example, sometimes TS would give me "Type instantiation is excessively deep and possibly infinite" seemingly at random, then I'd restart the language server, and it would return the expected type.
cc unified team: @wooorm
For example, sometimes TS would give me "Type instantiation is excessively deep and possibly infinite" seemingly at random
That error is caused by our type instantiation governor when a single source element gives rise to >5M type instantiations. Any code that triggers this is definitely highly suspect. It looks like you were barely managing to squeeze under the limit in 4.7, so I would strongly recommend simplifying the types. In particular, the InclusiveDescendant<...>
type appears expensive. I think it is trying to reduce the set of possible descendant types. I don't know how important that added precision is, but it clearly comes at a very high cost.
A TS wizard can probably improve InclusiveDescendant
. Itβs quite useful though, Iβd rather not yank it out if possible.
I've been looking at this one, and if you uncomment just the second commented-out snippet in the linked example repo, tsc
runs out of memory and crashes, so this isn't just an issue with tsserver/intellisense.
It seems like this code is generating huge unions of huge intersections of huge unions of... and so on, and post-#49119 we can't handle it anymore; it spends all its time traversing these in relation checking and doing so turns into a huge combinatorial explosion trying to see if two of these huge types are related.
So, just for reference, with TS 4.7, the example in my previous comment (the repro with the second block uncommented) takes ~2.18s to compile.
One thing I noticed while investigating this is that the intersections produced by the code here are big, but appear to be repetitive and only differ in ordering. In #52891 I am playing around with sorting intersections.
Just sorting the intersections themselves (nothing else) allows the example to compile in about 40 seconds, which is still Not Good :tm: but better than OOMing.
~However, @DanielRosenwasser pointed out that there were a few fast paths which now would work for intersections so now #52891 fully mitigates the performance problem and then some, bringing the compile time down to 1.56s, which is 40% faster!!~
I'm going to try and finalize this change, e.g. add origin types to intersections to fix the display issues, but given the nature of this change, it's not likely that this can go into TS 5.0 given we're nearly at RC.
Ugh.... nevermind, I screwed up; I had commented out the slow code in my example so I was testing the repro without modification! Very embarrassing.
There's still a benefit, which is still good compared to OOMing, but, not what I was hoping. Looking for more now.
That being said... it's still 40% for the non-bad case, which is promising in and of itself.
My q above still stands btw: if anyone knows of a better way to do this (https://github.com/microsoft/TypeScript/issues/51188#issuecomment-1294725244), I'd gladly use that. But I don't think the stuff I came up with is very weird, so other TS users might run into similar problems!
Unfortunately, I completely forgot that intersection ordering determines overload order, and therefore we can't sort intersections at all, so I'll have to go back to the drawing board on this.
I was looking at this again and was surprised to find that main no longer OOMs. It turns out that #53012 (which was backported to TS 5.0 just in time for the full release) stops the OOM on this code example. I can now compile the example in ~12s, which is still a lot slower than TS 4.7's ~2s, but at least it completes!
Bug Report
π Search Terms
tsserver typescript langauge server loading intellisense status indefinite error forever asserts assertion function vscode conditional type
π Version & Regression Information
4.7.4
and4.8.0-beta
and happens in all versions up to4.9.0-dev.20221015
β― Playground Link
Unfortunately, painstakingly copy-pasting all the types from the various packages into the playground doesn't allow me to reproduce the issue. So instead, I've created a minimal example repository that demonstrates the issue: https://github.com/Xunnamius/mre-typescript-issue-51188
π» Code
π Actual behavior
Tsserver and intellisense in vscode (latest version) hang when using a TypeScript version
>=4.8.0-beta
. See video example below.π Expected behavior
Tsserver/intellisense does not hang in latest versions of vscode and TypeScript.
https://user-images.githubusercontent.com/656017/195998496-e83d5c99-dc27-4867-8bcc-aa3d6a54ff55.mp4