Repository navigation
tsc and tsserver have different ideas of excessively deep types #32573
Description
Activity
This is probably an effect of the different check order. tsserver checks the currently open file first. That causes different evaluation order and caching for type instantiations.
Also, I'd like to note (again) that TS 3.5.1 builds this particular project in like 4-7 seconds (this includes the "problematic" file and lots of other files).
So, 14M instantiations isn't really a problem.Klaus Meinhardt (@ajafff) Some versions are okay, though =P
In my repro,
If I remove the file from
subproject-band build, it takes 1.41s.max count 1 max count 5 max count 30 max count 33 max count 51 max count 98 max count 123 max count 198 max count 243 max count 353 max count 1196 max count 1501 max count 3056 max count 6626 max count 21884 max count 145426 max count 276256 max count 4925257 Files: 373 Lines: 14338 Nodes: 67837 Identifiers: 21551 Symbols: 31339 Types: 17600 Memory used: 119849K Assignability cache size: 7096 Identity cache size: 0 Subtype cache size: 0 I/O Read time: 0.01s Parse time: 0.01s Program time: 0.11s Bind time: 0.02s Check time: 0.55s transformTime time: 0.76s Source Map time: 0.01s commentTime time: 0.01s printTime time: 0.74s Emit time: 0.74s I/O Write time: 0.01s Total time: 1.41sIf I add the offending file to a new
subproject-cand build, it takes 1.10s.
subproject-creferencessubproject-aandsubproject-b,
and only has one file.max count 5 max count 30 max count 32 max count 37 max count 44 max count 45 max count 51 max count 98 max count 123 max count 198 max count 353 max count 746 max count 12595 Files: 339 Lines: 14739 Nodes: 69534 Identifiers: 21824 Symbols: 16229 Types: 14113 Memory used: 55729K Assignability cache size: 3280 Identity cache size: 0 Subtype cache size: 0 I/O Read time: 0.01s Parse time: 0.17s Program time: 0.36s Bind time: 0.09s Check time: 0.50s transformTime time: 0.12s Source Map time: 0.00s commentTime time: 0.01s printTime time: 0.15s Emit time: 0.15s I/O Write time: 0.00s Total time: 1.10s
[Edit]
It looks like thees5.d.tsfile is causing the4,925,257instantiations?Just for reference,
I set the limit to 4,000,000,
var instantiationCount = 0; var maxCount = 0; function checkMaxCount (node) { if (instantiationCount > maxCount) { maxCount = instantiationCount; if (node.declarationList) { console.log("max count", instantiationCount, node); } } }
checkMaxCount(node); instantiationCount = 0;
if (instantiationDepth === 50 || instantiationCount >= 4000000) { error(currentNode, ts.Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); return errorType; }
This is the
node.declarationList.declarationswhen I set the limit to 4,000,000,[ Node { pos: 959, end: 971, kind: 238, id: 0, flags: 4194304, modifierFlagsCache: 536870912, transformFlags: 0, parent: Node { pos: 955, end: 971, kind: 239, id: 0, flags: 4194304, modifierFlagsCache: 0, transformFlags: 0, parent: [Node], original: undefined, declarations: [Circular] }, original: undefined, name: Node { pos: 959, end: 963, kind: 73, id: 0, flags: 4194304, modifierFlagsCache: 0, transformFlags: 0, parent: [Circular], original: undefined, escapedText: 'NaN', flowNode: [Object] }, type: Node { pos: 964, end: 971, kind: 136, id: 0, flags: 4194304, modifierFlagsCache: 0, transformFlags: 0, parent: [Circular], original: undefined }, initializer: undefined, symbol: Symbol { flags: 1, escapedName: 'NaN', declarations: [Array], valueDeclaration: [Circular], id: undefined, mergeId: undefined, parent: undefined, exports: Map {} } }, pos: 959, end: 971 ]
So,
NaNlives ines5.d.ts, I believe. Could the limit not be raised higher? =x
When I print out the
nodeitself,Node { pos: 0, end: 972, kind: 220, id: 0, flags: 4194304, modifierFlagsCache: 536870914, transformFlags: 0, parent: Node { pos: 0, end: 207082, kind: 285, id: 13293, flags: 4194336, modifierFlagsCache: 0, transformFlags: 0, parent: undefined, original: undefined, text: '/*! *****************************************************************************\nCopyright (c) Microsoft Corporation. All rights reserved. \nLicensed under the Apache License, Version 2.0 (the "License"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at http://www.apache.org/licenses/LICENSE-2.0 \n \nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, \nMERCHANTABLITY OR NON-INFRINGEMENT. \n \nSee the Apache Version 2.0 License for specific language governing permissions\nand limitations under the License.\n***************************************************************************** */\n\n\n\n/// <reference no-default-lib="true"/>\r\n\n\n/////////////////////////////\r\n/// ECMAScript APIs\r\n/////////////////////////////\r\n\r\ndeclare var NaN: number;\r\ndeclare var Infinity: number;\r\n\r\n/**\r\n * Evaluates JavaScript code and executes it.\r\n * @param x A String value that contains valid JavaScript code.\r\n */\r\ndeclare function eval(x: string): any;\r\n\r\n/**\r\n * Converts a string to an integer.\r\n * @param s A string to convert into a number.\r\n * @param radix A value between 2 and 36 that specifies the base of the number in numString.\r\n * If this argument is not supplied, strings with a prefix of \'0x\ /*snip*/ s An object that contains one or more properties that specify comparison options.\r\n */\r\n toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\r\n}\r\n', bindDiagnostics: [], bindSuggestionDiagnostics: undefined, languageVersion: 99, fileName: '/home/anyhowstep/node-projects/14m-vs-5m/node_modules/typescript/lib/lib.es5.d.ts', languageVariant: 0, isDeclarationFile: true, scriptKind: 3, pragmas: Map { 'reference' => [Object] }, checkJsDirective: undefined, referencedFiles: [], typeReferenceDirectives: [], libReferenceDirectives: [], amdDependencies: [], hasNoDefaultLib: true, statements: [ [Circular], [Node], [Node], /*snip*/ [Node], ... 40 more items, pos: 0, end: 207080 ], endOfFileToken: Node { pos: 207080, end: 207082, kind: 1, id: 0, flags: 4194304, modifierFlagsCache: 0, transformFlags: 0, parent: [Circular], original: undefined }, externalModuleIndicator: undefined, nodeCount: 13032, identifierCount: 4120, identifiers: Map { 'NaN' => 'NaN', 'Infinity' => 'Infinity', /*snip*/
Uhh...
So, going back to the original project I have for work,
I just fixed all of the "max instantiation depth" bugs I could find and this is happening,error TS2589: Type instantiation is excessively deep and possibly infinite.It doesn't even tell me what node is causing the problem!
My process was this,
- Build
- Max depth/count error?
- Look at file and line of diagnostics.
- Fix
- Go to step 1
However, now I get the max depth/count error and there is no file or line number.
So, I added the
maxCount()hack totsc.jsand kept the limit at 5,000,000 and rantscagain...And it's the same
es5.d.tsnode!So, for some projects, it gives 4.9M instantiations. And for others, > 5M and craps out.
I made the limit 14 million.
Then, I ran the build.It built fine.
But the
maxCountwas...max count 13837110 Node { pos: 0, end: 972, kind: 220, id: 0, flags: 4194304, modifierFlagsCache: 536870914, transformFlags: 0, parent: Node { pos: 0, end: 207082, kind: 285, id: 31661, flags: 4194336, modifierFlagsCache: 0, transformFlags: 0, parent: undefined, original: undefined, text: '/*! *****************************************************************************\nCopyright (c) Microsoft Corporation. All rights reserved. \nLicensed under the Apache License, Version 2.0 (the "License"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at http://www.apache.org/licenses/LICENSE-2.0 \n \nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, \nMERCHANTABLITY OR NON-INFRINGEMENT. \n \nSee the Apache Version 2.0 License for specific language governing permissions\nand limitations under the License.\n***************************************************************************** */\n\n\n\n/// <reference no-default-lib="true"/>\r\n\n\n/////////////////////////////\r\n/// ECMAScript APIs\r\n/////////////////////////////\r\n\r\ndeclare var NaN: number;\r\ndeclare var Infinity: number;\r\n\r\n/**\r\n * Evaluates JavaScript code and executes it.\r\n * @param x A String value that contains valid JavaScript code.\r\n */\r\ndeclare function eval(x: string): any;\r\n\r\n/**\r\n * Converts a string to an integer.\r\n * @param s A string to convert into a number.\r\n * @param radix A value between 2 and 36 that specifies the base of the number in numString.\r\n * If this argument is not supplied, strings with a prefix of \'0x\' are considered hexadecimal.\r\n * All other strings are considered decimal.\r\n */\r\ndeclare function parseInt(s: string, radix?: number): number;\r\n\r\n/**\r\n * Converts a string to a floating-point number.\r\n * @param string A string that contains a floating-point number.\r\n */\r\ndeclare function parseFloat(string: string): number;\r\n\r\n/**\r\n * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).\r\n * @param number A numeric value.\r\n */\r\ndeclare function isNaN(number: number): boolean;\r\n\r\n/**\r\n * Determines whether a supplied number is finite.\r\n * @param number Any numeric value.\r\n */\r\ndeclare function isFinite(number: number): boolean;\r\n\r\n/**\r\n * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).\r\n * @param encodedURI A value representing an encoded URI.\r\n */\r\ndeclare function decodeURI(encodedURI: string): string;\r\n\r\n/**\r\n * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).\r\n * @param encodedURIComponent A value representing an encoded URI component.\r\n */\r\ndeclare function decodeURIComponent(encodedURIComponent: string): string;\r\n\r\n/**\r\n * Encodes a text string as a valid Uniform Resource Identifier (URI)\r\n * @param uri A value representing an encoded URI.\r\n */\r\ndeclare function encodeURI(uri: string): string;\r\n\r\n/**\r\n * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).\r\n * @param uriComponent A value representing an encoded URI component.\r\n */\r\ndeclare function encodeURIComponent(uriComponent: string | number | boolean): string;\r\n\r\n/**\r\n * Computes a new string in which certain characters have been replaced by a hexadecimal escape seq /*snip*/When I take the
textand dotext.substr(0, 972), I get,"/*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /// <reference no-default-lib="true"/> ///////////////////////////// /// ECMAScript APIs ///////////////////////////// declare var NaN: number;"How does
NaNgive 13.8M instantiations!?RyanCavanaugh commented
on Jul 26, 2019 MemberMore actionstsserverintrinsically doesn't have to do as much work to provide completion info astscdoes to ensure there are no errors in your project in a batch scenario. And, as, noted, if your code is extremely complex (it seems like this is common in your projects), the ordering in which types are inspected can results in errors in some cases and not others.I changed it to,
checkMaxCount(saveCurrentNode)and got,max count 1502701 undefined max count 2885368 undefined max count 13837110 undefinedSorry for the spam =(
I'm just anxious that my code will break with 3.6 and I won't be able to migrate my projects.
So, I'm pretty desperate to find a solution that makes sense to me.
I think one of my gripes with this situation is that I've now discovered I can get the max count error and not know how to fix it because
tscwon't tell me where the error is.I'd like to stress again that in 3.5.1, these files compile in mere seconds. So it's not like having 14M, 16M, 20M instantiations is actually a real problem.
And inspecting the node just tells me
es5.d.ts.I can't just not use
es5.d.tsand I can't fixes5.d.ts99% sure I just have the wrong idea and I'm inspecting the wrong things and drawing the wrong conclusion. But I still don't know where the count hits 13.8M
What should I look out for when trying to find the 13.8M culprit? Any variables I should be monitoring besides
nodeandcurrentNode?- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Jul 31, 2019 Wesley Wigham (@weswigham) 's comment here jumped out at me,
#32707 (comment)It probably indicates a codepath we neglect to set a
currentNodeon.Because it's related to this,
#32573 (comment)I just fixed all of the "max instantiation depth" bugs I could find and this is happening,
error TS2589: Type instantiation is excessively deep and possibly infinite.It doesn't even tell me what node is causing the problem!
And this,
#32573 (comment)I can get the max count error and not know how to fix it because
tscwon't tell me where the error is.
TypeScript Version:
typescript-3.6.0-insiders.20190725https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/37759/artifacts?artifactName=tgz&fileId=2A7E3F3E93DD6F833D63A63F3A7A21707B3F57B08FCA5C93A8F1848556D8141F02&fileName=/typescript-3.6.0-insiders.20190725.tgz
Taken from,
#32028 (comment)
Search Terms:
max instantiation count, max instantiation depth, tsc, tsserver
Code
I've reduced the 40-subproject monorepo to just small parts of 2 subprojects.
Here is a snippet of the problem,
Expected behavior:
If
tscgets the error,Then
tsservershould also get the errorActual behavior:
tscgets the error, buttsserverdoes not (or at least VS code infers the type correctly without errors)Playground Link:
-None-
Sheetal Nandi (@sheetalkamat)
The project involved contains code related to a company project.
So, I really do not want to upload it publicly, if possible.
I could mangle the variable names so that they're meaningless but if I can just email the parts of the project that are involved, that would be nice.
Repro steps:
npm installnpm run buildTS2589: Type instantiation is excessively deep and possibly infinite.tscsays contains errorsRelated Issues:
The merged PR that introduced the error,
#32079 (comment)
The build I am testing,
#32028
Also relevant, #29511
It seems like every few versions, there ends up being a difference between
tscandtsserver, regarding the max instantiation depth