Skip to content

fix(ts): bound recursive member lookup work - #2280

Open
dianshu wants to merge 2 commits into
DeusData:mainfrom
dianshu:fix/ts-bounded-lookup
Open

dianshu wants to merge 2 commits into
DeusData:mainfrom
dianshu:fix/ts-bounded-lookup

Conversation

@dianshu

@dianshu dianshu commented Sep 22, 2026 •

Copy link
Copy Markdown

What does this PR do?

Bounds recursive TypeScript member and method lookup on cyclic and highly
branching type graphs.

  • uses per-lookup depth and work budgets instead of shared context depth;
  • tracks the shallowest depth at which each type was visited, allowing a type
    reached first through a deeper path to be reconsidered through a shallower
    path;
  • applies the same bounded traversal model to member and method lookup;
  • removes the obsolete shared member_depth field;
  • adds regression coverage for cyclic graphs, branching cycles, inherited
    methods, and shallower revisits.

Before this change, a cyclic type graph could overflow the ASan stack, while a
depth-only guard still allowed branching cyclic graphs to exceed the 30-second
test watchdog.

This contribution was prepared with AI assistance and reviewed and submitted
by the human account owner.

Verification

  • scripts/test.sh: 8172 passed, 0 failed, 8 skipped
  • Reproduce and verify: scripts/test.sh --suites "ts_lsp stack_overflow_b" (313 passed). Before the fix, lsp_ts_cyclic_types_no_crash overflowed the ASan stack; a depth-only guard still caused lsp_ts_branching_cycle_has_bounded_work to exceed its 30-second watchdog.
  • make -f Makefile.cbm lint-format CLANG_FORMAT=clang-format-20
  • git diff --check

Checklist

  • Every commit is signed off
  • Tests pass locally
  • Format check passes
  • New behavior is covered by reproduce-first regression tests

Signed-off-by: dianshu <dianshu@123.com>
@dianshu
dianshu requested a review from DeusData as a code owner September 22, 2026 10:14
@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@DeusData DeusData left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you — replacing the shared member_depth guard with per-lookup state (a depth limit, plus a visited table that re-enters a type only at a shallower depth) is the right structure, and it closes the cycle blow-up cleanly.

Two things before it merges, both from standing rules of the codebase:

  1. The 4096-step budget silently decides graph content. When it runs out, the lookup returns UNKNOWN with no log or counter, and a CALLS edge disappears without a trace. Our rule is that no work cap may silently decide what lands in the graph. Here the visited table already bounds the work (each type is re-entered at most once per shallower depth, so at most 64 times), so the budget looks redundant: please drop it. If you find a case it is still needed for, make hitting it loud, with a counter or log line that a test asserts on.
  2. A timeout must not decide a test verdict. lsp_ts_branching_cycle_has_bounded_work and lsp_ts_cyclic_types_no_crash pass or fail on the alarm(30) watchdog. Please replace that with a deterministic work counter exposed behind CBM_ENABLE_TEST_SEAMS, and assert it stays within the proven bound. That also lets the branching test run on Windows instead of being skipped.

The shallower-revisit test is a good guard for the visited-depth logic. Thank you again.

Signed-off-by: dianshu <dianshu@123.com>

This branch has not been deployed

No deployments
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