Skip to content
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

Bug: Eslint hangs and gobbles memory with i18next version 22 and typescript-eslint #6538

Closed
4 tasks done
raigoinabox opened this issue Feb 27, 2023 · 5 comments
Closed
4 tasks done
Labels
bug Something isn't working external This issue is with another package, not typescript-eslint itself package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@raigoinabox
Copy link

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Issue Description

I type in "eslint src" and eslint would hang and start gobbling memory.

After it has taken about 4 gigs of memory, node would throw an out of memory error.

I have made a minimal reproduction example repo in github.

It seems to be a complex bug through the interplay between typescript-eslint and i18next.
I first discovered it by upgrading to i18next version 22. They did a major typescript rewrite
for that version. It can be seen from this repo as well, if i18next is removed, the bug disappears.
These are things I have tried to change, and then notice that the bug goes away:

  • remove i18next.d.ts file (or any code in there)
  • remove i18next package
  • move i18next to the src directory
  • in eslint conf replace "plugin:@typescript-eslint/recommended-requiring-type-checking" with "plugin:@typescript-eslint/recommended"
  • change the content of src/broken.ts in any way.

Reproduction Repository Link

https://github.com/raigoinabox/typescript-eslint-hang-bug

Repro Steps

  1. clone the repo
  2. npm install
  3. npx eslint src

Versions

package version
@typescript-eslint/eslint-plugin 5.53.0
@typescript-eslint/parser 5.53.0
@typescript-eslint/scope-manager 5.53.0
@typescript-eslint/typescript-estree 5.53.0
@typescript-eslint/type-utils 5.53.0
@typescript-eslint/utils 5.53.0
TypeScript 4.9.5
ESLint 8.35.0
node 16.19.1
@raigoinabox raigoinabox added bug Something isn't working triage Waiting for team members to take a look labels Feb 27, 2023
@esetnik
Copy link
Contributor

esetnik commented Feb 28, 2023

There is another minimal reproduction available here i18next/i18next#1901 and a report of the same issue in i18next/i18next#1883

@esetnik
Copy link
Contributor

esetnik commented Feb 28, 2023

We believe the issue is caused by the usage of the @typescript-eslint/no-misused-promises rule.

@bradzacher
Copy link
Member

no-misused-promises will interrogate function arguments by default to look for incorrect function returns like assigning () => Promise<T> to a location expecting () => void (which is valid in TS but not always safe).

To do this we need to ask TS to do some deep interrogation of the types of the parameter and the argument. Which means we'll deeply inspect both the t and the TFunction types.

Having a quick glance at the definition of TFunction, it has 12 call signatures and each one returns a really complicated recursive conditional types... There's just a whole lot of stuff that TS has to track and unwrap to tell us what the return type might be.

We don't even store the type - we just calculate it, figure out if it's a void or promise returning function, then discard it - so the memory usage is due to TS having to calculate so much.

I saw in one of the issues that someone was even encountering OOMs with just tsc. Note that types are computed lazily, and the checks we do in rules do cause more computation than you might encounter in a standard tsc check, which is why not everyone encounters OOMs that way.

I don't think there's anything that we can do here - these types are just ridiculously complex spaghetti. If someone wants to dig deeper into the rule and figure out if there's a way to optimise it - happy to accept a PR, but I think this can only be fixed from the library side.

@bradzacher bradzacher added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin awaiting response Issues waiting for a reply from the OP or another party and removed triage Waiting for team members to take a look labels Feb 28, 2023
@raigoinabox
Copy link
Author

Sorry about the bug report then, I did search for a report in typescript-eslint, but forgot to look in the i18next issue tracker. 🙂

I either way am happy that I went through creating the minimal reproduction example, as I learned to avoid the problem in my own project by not taking TFunction as a parameter and using the imported t value directly (which in the new i18next is better anyhow).

I'll leave it up to you what to do with this bug report, you may close it if you wish.

Thank you for your time. 🙂

@bradzacher
Copy link
Member

No problem!
I'll go ahead and close this as unactionable from our side.

If anyone does have any ideas on how we might improve the perf, always happy to accept PRs!

@bradzacher bradzacher closed this as not planned Won't fix, can't repro, duplicate, stale Mar 1, 2023
@bradzacher bradzacher added external This issue is with another package, not typescript-eslint itself and removed awaiting response Issues waiting for a reply from the OP or another party labels Mar 1, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working external This issue is with another package, not typescript-eslint itself package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

No branches or pull requests

3 participants