Open AnyhowStep opened 5 years ago
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.
@ajafff Some versions are okay, though =P
In my repro,
If I remove the file from subproject-b
and 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.41s
If I add the offending file to a new subproject-c
and build, it takes 1.10s.
subproject-c
references subproject-a
and subproject-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 the es5.d.ts
file is causing the 4,925,257
instantiations?
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.declarations
when 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, NaN
lives in es5.d.ts
, I believe. Could the limit not be raised higher? =x
When I print out the node
itself,
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,
However, now I get the max depth/count error and there is no file or line number.
So, I added the maxCount()
hack to tsc.js
and kept the limit at 5,000,000 and ran tsc
again...
And it's the same es5.d.ts
node!
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 maxCount
was...
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 text
and do text.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 NaN
give 13.8M instantiations!?
tsserver
intrinsically doesn't have to do as much work to provide completion info as tsc
does 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 undefined
Sorry 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 tsc
won'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.ts
and I can't fix es5.d.ts
99% 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 node
and currentNode
?
@weswigham 's comment here jumped out at me, https://github.com/microsoft/TypeScript/issues/32707#issuecomment-518102872
It probably indicates a codepath we neglect to set a
currentNode
on.
Because it's related to this, https://github.com/microsoft/TypeScript/issues/32573#issuecomment-515527272
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, https://github.com/microsoft/TypeScript/issues/32573#issuecomment-515532751
I can get the max count error and not know how to fix it because
tsc
won't tell me where the error is.
TypeScript Version:
typescript-3.6.0-insiders.20190725
https://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, https://github.com/microsoft/TypeScript/pull/32028#issuecomment-515234327
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
tsc
gets the error,Then
tsserver
should also get the errorActual behavior:
tsc
gets the error, buttsserver
does not (or at least VS code infers the type correctly without errors)Playground Link:
-None-
@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 install
npm run build
TS2589: Type instantiation is excessively deep and possibly infinite.
tsc
says contains errorsRelated Issues:
The merged PR that introduced the error, https://github.com/microsoft/TypeScript/pull/32079#issuecomment-515334873
The build I am testing, https://github.com/microsoft/TypeScript/pull/32028
Also relevant, https://github.com/microsoft/TypeScript/issues/29511 It seems like every few versions, there ends up being a difference between
tsc
andtsserver
, regarding the max instantiation depth