Skip to content

fix(no-floating-promises): avoid recursive checker calls#977

Draft
camc314 wants to merge 1 commit into
mainfrom
codex/no-floating-promises-recursive-type-args
Draft

fix(no-floating-promises): avoid recursive checker calls#977
camc314 wants to merge 1 commit into
mainfrom
codex/no-floating-promises-recursive-type-args

Conversation

@camc314

@camc314 camc314 commented May 19, 2026

Copy link
Copy Markdown
Contributor

Stacked on #976.

This re-enables the recursive CustomNode no-floating-promises cases. The rule now avoids full argument-sensitive call resolution only when the callee return signatures are already enough to prove the expression cannot produce a promise or promise array.

The guard deliberately does not fire for return types that still need call-site instantiation, including type variables, conditional types, indexed access types, substitution types, unions/intersections containing them, or array/tuple element types containing them. That keeps generic array-returning cases such as .map(...) and generic conditional promise returns on the normal checker path.

This follows the failure mode from typescript-eslint/typescript-eslint#12294 without adding a panic/recover wrapper or matching the regression test shape directly.

Validation:

  • UPDATE_SNAPS=true go test ./internal/rules/no_floating_promises/... -timeout=60s
  • go test ./internal/rules/no_floating_promises/... -timeout=60s

@camc314 camc314 self-assigned this May 19, 2026
@camc314 camc314 force-pushed the codex/no-floating-promises-spread-handler branch from eea92ec to ed033d2 Compare May 19, 2026 10:59
@camc314 camc314 force-pushed the codex/no-floating-promises-recursive-type-args branch from a7eff35 to 22df9f9 Compare May 19, 2026 10:59
@graphite-app graphite-app Bot force-pushed the codex/no-floating-promises-spread-handler branch from ed033d2 to 4d71eb8 Compare May 19, 2026 11:08
@camc314 camc314 force-pushed the codex/no-floating-promises-recursive-type-args branch from 22df9f9 to 4ec1443 Compare May 19, 2026 11:14
Base automatically changed from codex/no-floating-promises-spread-handler to main May 19, 2026 11:15
@camc314 camc314 force-pushed the codex/no-floating-promises-recursive-type-args branch from 4ec1443 to 44d3ec7 Compare May 19, 2026 11:15
@camc314 camc314 force-pushed the codex/no-floating-promises-recursive-type-args branch from 44d3ec7 to 3c6aec7 Compare May 19, 2026 11:33
@amirt01

amirt01 commented Jun 28, 2026

Copy link
Copy Markdown

Hit this exact failure mode from a real-world library, not just a synthetic test case — wanted to add it as a data point since it shows the recursive-type pattern this PR guards against does occur in published .d.ts files.

Upgrading three/@types/three from 0.184.00.185.0 makes tsgolint (via oxlint --type-aware) hang indefinitely on this file (lints clean, 0 warnings/errors, on 0.184.0):

import { float } from "three/tsl";
import type Node from "three/src/nodes/core/Node.js";

const x = float(1.0);

export async function check() {
  await Promise.resolve(x).then((val: Node) => {
    console.log(val);
  });
}
  • tsc --noEmit on the same file finishes in well under a second with no errors on both versions.
  • oxlint --type-aware finishes instantly on 0.184.0, hangs indefinitely on 0.185.0 (killed after 60+ minutes of CPU-pegged runtime).
  • Root cause on the types side: @types/three@0.185.0 refactored Node<TNodeType> (src/nodes/core/Node.d.ts) to use unconstrained generic interfaces (FloatOrVecExtensions<TNodeType>, IntOrVecExtensions<TNodeType>, UintOrVecExtensions<TNodeType>, BoolOrVecExtensions<TNodeType>) merged via declare module across many files (MathNode.d.ts, OperatorNode.d.ts, etc.), where every merged method returns Node<TNodeType> — a self-reference back into the same conditional type, now fanned out across dozens of cross-file merges instead of one concrete interface per type. That's structurally the same "recursive type forces call-site instantiation" shape that this PR is narrowing the rule's fast path around.

Versions: three@0.185.0, @types/three@0.185.0, oxlint@1.71.0, oxlint-tsgolint@0.23.0.

Happy to share the full repro repo if useful — currently it's a 4-file project (package.json, tsconfig.json, repro.ts).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants