perf(nursery/noFloatingPromises): skip type inference for assignment statements - #10991
BezSaharaD wants to merge 3 commits into
Conversation
…statements is_handled_promise() unconditionally treats a bare assignment expression-statement as handled, regardless of its type -- so there's no need to run full type inference (ctx.type_of_expression) just to be told that afterwards. Check for an assignment expression first, before the type computation, and bail out early in that case. Measured via --profile-rules on a large real-world TypeScript/React project: this rule's cumulative cost dropped from ~52s to ~37s (~29%), and its worst-case single-call time dropped from 92ms to 30ms. Smaller than the noMisusedPromises fix in a prior PR since fewer of this rule's (already query-narrowed) invocations hit the pattern, but a real, measured improvement with byte-identical diagnostics before and after (11331 errors both times). Added a regression test fixture (assignmentIsHandled.ts) alongside the existing spec suite. All 61 rule tests (60 existing + 1 new) and all 478 nursery-group tests pass.
🦋 Changeset detectedLatest commit: 990334a The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Organic activityNo automation signals detected in the analyzed events. This is an automated analysis by AgentScan |
Merging this PR will not alter performance
Comparing Footnotes
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/perf-no-floating-promises.md:
- Line 5: Update the changeset description for noFloatingPromises to include the
required issue, rule, and assist links. Preserve the existing rule link, add the
applicable issue and assist links using the repository’s standard changeset link
format, or explicitly confirm when either link does not exist.
In `@crates/biome_js_analyze/src/lint/nursery/no_floating_promises.rs`:
- Around line 180-182: Add a rustdoc note to the no_floating_promises rule
declaration documenting that bare assignment statements are treated as handled
regardless of type. Place the documentation on the rule declaration associated
with is_handled_promise, preserving the existing internal comment and rule
behavior.
- Around line 183-188: Remove or relocate the early return for
JsAssignmentExpression in the promise analysis flow so assignments continue
through the ArrayOfPromises handling, including cases such as target =
[returnsPromise()]. Preserve the existing branch ordering and add a regression
test covering an assignment containing an array of promises.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 174b7130-fcfe-431a-9eee-fb627d0be360
⛔ Files ignored due to path filters (1)
crates/biome_js_analyze/tests/specs/nursery/noFloatingPromises/assignmentIsHandled.ts.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (3)
.changeset/perf-no-floating-promises.mdcrates/biome_js_analyze/src/lint/nursery/no_floating_promises.rscrates/biome_js_analyze/tests/specs/nursery/noFloatingPromises/assignmentIsHandled.ts
…gression test - Add a rustdoc bullet point and a "Valid" example showing that assigning a floating promise to a variable is considered handled (previously only explained by an internal comment). - Add assignmentOfArrayIsHandled.ts: verified that assigning the result of an array-producing call with an async callback (e.g. `target = arr.map(async (x) => ...)`) is also not flagged, and that this is unchanged by the assignment-expression bail-out (checked both with and without that bail-out; same result either way, since the assignment expression's type isn't resolved to an array type by the underlying type inference regardless). Verified: all 61 noFloatingPromises spec tests and all 480 nursery-group tests pass.
ematipico
left a comment
There was a problem hiding this comment.
Looks good. Do we have a case where we assign to a target and then call the target? Is that handled correctly?
| // `is_handled_promise` (below) always treats a bare assignment | ||
| // statement as handled, regardless of its type -- so there's no | ||
| // point paying for type inference just to be told that afterwards. |
There was a problem hiding this comment.
This comment is weird. Can't we just update is_handled_promise to take in consideration this new logic.
If not, just remove it. This will become the new logic
There was a problem hiding this comment.
Please remove all those comments from the new cases. Only the ones at the top are the ones that matter
|
Hello, I apologize for deleting the repositories. I forgot that I have open PRs. I deleted them for personal reasons and being busy with the main project. I do not claim any code or credit, but you can take the code if needed. |
Summary
is_handled_promise()unconditionally treats a bare assignment expression-statement (e.g.x = getPromise();) as handled, regardless of its type. That check runs afterctx.type_of_expression(&expression)-- full type inference -- meaning the inference result is computed and then simply discarded for this case. Checking for an assignment expression first (a cheap, purely syntactic check) and bailing out before the type computation skips that wasted work.Measurement
Profiled with
--profile-ruleson the same large real-world project as #10990:Smaller improvement than #10990's ~4.7x, since this rule's
Query(Typed<JsExpressionStatement>, statement-level only) is already much narrower thannoMisusedPromises's (Typed<AnyJsExpression>, every expression) -- there was less redundant work to remove to begin with. Diagnostics are byte-identical before/after (11331 errors both times).Testing
assignmentIsHandled.tsas a new regression fixture (generated its snapshot viaINSTA_UPDATE=always).noFloatingPromisesspec tests (60 existing + 1 new) pass.nurseryrule group pass unchanged.Disclosure
Found and fixed with Claude's (Anthropic) assistance while continuing the profiling from #10990 against the same real-world project - reviewed and verified locally (unit tests, byte-identical diagnostic diff, release build) before submitting.