Skip to content

fix(inference): improve member and Promise inference - #10971

Merged
ematipico merged 5 commits into
mainfrom
08-member-promise-await-inference
Jul 20, 2026
Merged

ematipico merged 5 commits into
mainfrom
08-member-promise-await-inference

Conversation

@ematipico

@ematipico ematipico commented Jul 17, 2026 •

Copy link
Copy Markdown
Member

Summary

Improves internal member, array, Promise, and await inference. The new engine resolves additional inherited, computed, intersection, generic, and chained member shapes while preserving non-Promise branches of awaited unions. No lint rule changes inference engines in this PR, so no changeset is included.

Test Plan

Extended module graph tests for member chains, typed arrays, Promise results, and await expressions.

Docs

N/A

This PR was created with AI assistance (OpenCode).

@changeset-bot

changeset-bot Bot commented Jul 17, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bfe5d78

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

✅ Organic activity

No automation signals detected in the analyzed events.

View full analysis →

This is an automated analysis by AgentScan

@github-actions github-actions Bot added A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Jul 17, 2026
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 17, 2026 13:12
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from cf9f112 to 1bb5720 Compare July 17, 2026 13:13
@ematipico
ematipico force-pushed the graphite-base/10971 branch from 9d9f35a to 2c81541 Compare July 17, 2026 13:13
@ematipico
ematipico changed the base branch from graphite-base/10971 to 07-overload-expected-argument-inference July 17, 2026 13:14
@github-actions github-actions Bot removed the A-Linter Area: linter label Jul 17, 2026
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 17, 2026 14:05
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from 1bb5720 to efbb8c9 Compare July 17, 2026 14:06
@ematipico
ematipico force-pushed the graphite-base/10971 branch from 2c81541 to 6e59183 Compare July 17, 2026 14:06
@ematipico
ematipico changed the base branch from graphite-base/10971 to 07-overload-expected-argument-inference July 17, 2026 14:06
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 18, 2026 09:55
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from efbb8c9 to 7bc7004 Compare July 18, 2026 09:56
@ematipico
ematipico force-pushed the graphite-base/10971 branch from 6e59183 to dd1cc2c Compare July 18, 2026 09:56
@ematipico
ematipico changed the base branch from graphite-base/10971 to 07-overload-expected-argument-inference July 18, 2026 09:56
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 18, 2026 09:57
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from 7bc7004 to d4621d0 Compare July 18, 2026 11:50
@ematipico
ematipico force-pushed the graphite-base/10971 branch from dd1cc2c to cb77297 Compare July 18, 2026 11:50
@ematipico
ematipico changed the base branch from graphite-base/10971 to 07-overload-expected-argument-inference July 18, 2026 11:50
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 18, 2026 11:50
@ematipico
ematipico force-pushed the graphite-base/10971 branch from cb77297 to 3e0b12a Compare July 18, 2026 12:05
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from d4621d0 to e8bb18f Compare July 18, 2026 12:05
@ematipico
ematipico changed the base branch from graphite-base/10971 to 07-overload-expected-argument-inference July 18, 2026 12:05
@ematipico
ematipico changed the base branch from 07-overload-expected-argument-inference to graphite-base/10971 July 18, 2026 12:05
@ematipico
ematipico force-pushed the graphite-base/10971 branch from 3e0b12a to 4bf9b21 Compare July 19, 2026 15:05
@ematipico
ematipico force-pushed the 08-member-promise-await-inference branch from e8bb18f to 04f414a Compare July 19, 2026 15:05
@ematipico
ematipico changed the base branch from graphite-base/10971 to main July 19, 2026 15:05
@ematipico
ematipico marked this pull request as ready for review July 19, 2026 15:06
@coderabbitai

coderabbitai Bot commented Jul 19, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fcec7234-2f62-40c1-88d1-6a48cc72392f

📥 Commits

Reviewing files that changed from the base of the PR and between 90ef237 and bfe5d78.

📒 Files selected for processing (1)
  • crates/biome_module_graph/tests/spec_tests_v2/substitutions.test.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_module_graph/tests/spec_tests_v2/substitutions.test.rs

Walkthrough

The module graph type inference engine preserves local handles for recursive cycles and resolves this with enclosing generic parameters. Member lookup now supports resolved classes, instances, computed string keys, inherited statics, arrays, in-progress locals, and Promise methods. Generic defaults are applied to unresolved return references, with expanded Promise, await, member, and substitution specification coverage.

Possibly related PRs

Suggested labels: A-Type-Inference

Suggested reviewers: dyc3

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is clear, concise, and matches the main inference improvements in the changeset.
Description check ✅ Passed The description accurately summarises the member, array, Promise, and await inference changes and the related test updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 08-member-promise-await-inference

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@crates/biome_module_graph/src/db/queries/type_inference.rs`:
- Around line 1849-1862: Update the default-resolution loop around
function.type_parameters(db) so each generic default is substituted through all
previously accumulated substitutions before replacing the current generic.
Ensure chained defaults such as T = string and U = T resolve U to string rather
than leaving T, and add a regression case covering dependent defaults.

In `@crates/biome_module_graph/tests/spec_tests_v2.rs`:
- Around line 4202-4206: The snapshot key passed to
assert_inferred_type_snapshot in
test_infer_module_types_resolves_inherited_static_members is incorrect; rename
it to match that test’s inherited-static behavior, rather than the copied
resolves_this_member_in_object_method name.
🪄 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: e369659b-8173-4f65-8110-62ffb152f5eb

📥 Commits

Reviewing files that changed from the base of the PR and between 4bf9b21 and 04f414a.

⛔ Files ignored due to path filters (16)
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_selects_function_declaration_overload_by_callback_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_selects_imported_function_declaration_overload_by_callback_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_substitutes_generic_from_callback_promise_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_substitutes_generic_from_callback_promise_union_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_substitutes_generic_inside_promise_union_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_substitutes_multiple_generics_inside_union_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_call_expression_type_substitutes_nested_generic_return_type.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_evaluates_await_expressions_on_build.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_evaluates_await_union_expressions_on_build.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_evaluates_this_and_super_edge_expressions_on_build.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_infers_new_expression_nested_generic_instances_on_build.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_preserves_floating_promise_shapes.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_preserves_generic_class_this_parameters.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_preserves_new_expression_generic_instances_on_build.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_resolves_promise_member_chain.snap is excluded by !**/*.snap and included by **
  • crates/biome_module_graph/tests/snapshots/test_infer_module_types_resolves_this_member_in_object_method.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (6)
  • crates/biome_module_graph/src/db/queries/type_inference.rs
  • crates/biome_module_graph/src/db/type_inference/expressions.rs
  • crates/biome_module_graph/src/db/type_inference/lookup.rs
  • crates/biome_module_graph/src/db/type_inference/qualifiers.rs
  • crates/biome_module_graph/src/db/type_inference/resolver.rs
  • crates/biome_module_graph/tests/spec_tests_v2.rs

Comment thread crates/biome_module_graph/src/db/queries/type_inference.rs
Comment thread crates/biome_module_graph/tests/spec_tests_v2.rs
@codspeed

codspeed Bot commented Jul 19, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 0 benchmarks

⚡ 1 improved benchmark
❌ 1 (👁 1) regressed benchmark
✅ 19 untouched benchmarks
⏩ 252 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
⚡ bench_index_d_ts_salsa_invalidated[react/index.d.ts] 9.3 ms 8 ms +16.49%
👁 bench_index_d_ts_salsa_invalidated[astro_server.mjs] 28.7 ms 32.2 ms -10.77%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing 08-member-promise-await-inference (bfe5d78) with main (4bf9b21)

Open in CodSpeed

Footnotes

  1. 252 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/biome_module_graph/src/db/type_inference/expressions.rs (2)

1159-1258: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Static vs. instance members aren't distinguished in the in-progress fast path.

resolve_in_progress_local_member matches class.members purely by has_name(member_name), with no check against member.kind.is_static(). Both call sites (Line 973-976 for a direct static access, Line 987-990 for an instance access) rely on this, so a class with both a static and instance member sharing the same name (legal in JS/TS, they live on different sides) can return the wrong one whenever the enclosing class is still in_progress (e.g. resolved via this/self-reference). The normal traversal path threads MemberLookupMode everywhere else — this fast path silently drops that discrimination.

🛠️ Proposed fix
     fn resolve_in_progress_local_member(
         &mut self,
         local: InferredLocalTypeHandle<'db>,
         member_name: &str,
+        is_static: bool,
     ) -> Option<InferredTypeData<'db>> {
         ...
         let member = match raw {
-            RawTypeData::Class(class) => class
-                .members
-                .iter()
-                .find(|member| member.kind.has_name(member_name)),
+            RawTypeData::Class(class) => class.members.iter().find(|member| {
+                member.kind.has_name(member_name) && member.kind.is_static() == is_static
+            }),
             RawTypeData::Interface(interface) => interface

Callers then pass the appropriate flag:

// Line 973-976 (static access on the object itself)
self.resolve_in_progress_local_member(local, member_name, true)
// Line 987-990 (access through an instance)
self.resolve_in_progress_local_member(local, member_name, false)

Also applies to: 973-976, 987-990

🤖 Prompt for 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.

In `@crates/biome_module_graph/src/db/type_inference/expressions.rs` around lines
1159 - 1258, Update resolve_in_progress_local_member to accept a static-member
flag and filter class member matching by member.kind.is_static() accordingly.
Pass true from the direct static access call site and false from the instance
access call site, while preserving existing behavior for interfaces, objects,
and literals.

1077-1094: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Tuple/Array member lookup should cross InstanceOf The tuple branch builds a raw Array lookup and applies substitutions afterwards, so crossed_instance never flips to true and resolve_member_references() is skipped. Use the normal InstanceOf path here so generic return types on methods like .pop()/.shift() don’t stay unresolved.

🤖 Prompt for 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.

In `@crates/biome_module_graph/src/db/type_inference/expressions.rs` around lines
1077 - 1094, Update the tuple branch of the member lookup logic to route the
resolved Array type through the normal InstanceOf path instead of directly
calling find_member_type_on_resolved_type. Preserve the tuple element union and
Array substitutions, while ensuring crossed_instance becomes true so
resolve_member_references() resolves generic method return types such as pop()
and shift().
🤖 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 `@crates/biome_module_graph/src/db/type_inference/lookup.rs`:
- Around line 506-511: Update the Class arm in the type lookup match to pass
mode.allows_index_signature() to find, matching the Interface, Object, and
Literal(Object) arms. Remove the matches!(mode, MemberLookupMode::Instance)
check so MemberLookupMode::Any also permits index-signature fallback.

In `@crates/biome_module_graph/tests/spec_tests_v2/substitutions.test.rs`:
- Around line 109-113: Update the assertion in the substitution test to verify
that success_ty is the canonical InferredTypeData::Boolean union containing both
true and false branches, rather than relying on is_inferred_boolean, which also
accepts a single literal. Preserve the existing diagnostic context when the
assertion fails.

---

Outside diff comments:
In `@crates/biome_module_graph/src/db/type_inference/expressions.rs`:
- Around line 1159-1258: Update resolve_in_progress_local_member to accept a
static-member flag and filter class member matching by member.kind.is_static()
accordingly. Pass true from the direct static access call site and false from
the instance access call site, while preserving existing behavior for
interfaces, objects, and literals.
- Around line 1077-1094: Update the tuple branch of the member lookup logic to
route the resolved Array type through the normal InstanceOf path instead of
directly calling find_member_type_on_resolved_type. Preserve the tuple element
union and Array substitutions, while ensuring crossed_instance becomes true so
resolve_member_references() resolves generic method return types such as pop()
and shift().
🪄 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: f2ef0fa6-49e3-4084-88af-c8111aa96dba

📥 Commits

Reviewing files that changed from the base of the PR and between 69deea2 and 90ef237.

📒 Files selected for processing (3)
  • crates/biome_module_graph/src/db/type_inference/expressions.rs
  • crates/biome_module_graph/src/db/type_inference/lookup.rs
  • crates/biome_module_graph/tests/spec_tests_v2/substitutions.test.rs

Comment thread crates/biome_module_graph/src/db/type_inference/lookup.rs
Comment thread crates/biome_module_graph/tests/spec_tests_v2/substitutions.test.rs Outdated
/// Member lookup runs both while raw module types are being converted and
/// after inferred type tables are available. Implementations supply the local
/// type resolution and member finalization appropriate for either phase.
pub(in crate::db::type_inference) trait MemberLookupResolver<'db> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The member lookup logic has been moved into this trait, because it's now a shared logic and there was a regression caused by the two original logic to drift

Comment thread crates/biome_module_graph/src/db/type_inference/lookup.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant