Skip to content

Short-circuit NoReturn analysis for Any or Unknown calls - #11419

Open
Bill Schnurr (bschnurr) wants to merge 3 commits into
microsoft:mainfrom
bschnurr:perf/no-return-unknown-guard
Open

Short-circuit NoReturn analysis for Any or Unknown calls#11419
Bill Schnurr (bschnurr) wants to merge 3 commits into
microsoft:mainfrom
bschnurr:perf/no-return-unknown-guard

Conversation

@bschnurr

@bschnurr Bill Schnurr (bschnurr) commented May 6, 2026

Copy link
Copy Markdown
Member

Summary

  • Stops NoReturn call analysis as soon as a callable union subtype is Any or Unknown.
  • Uses a single-pass subtype loop with a true early exit.
  • Adds coverage for both NoReturn | Unknown and NoReturn | Any call targets.

Why the early exit is correct

A call is considered NoReturn only when every possible call-target subtype is known not to return normally. Any and Unknown can represent a NoReturn callable, but they can also represent a callable that returns normally. They therefore provide insufficient information to prove that the call does not return.

This is also equivalent to the previous counting implementation. Each subtype increments subtypeCount, but an Any or Unknown subtype matches none of the cases that increment noReturnTypeCount. Once one is encountered, noReturnTypeCount === subtypeCount cannot be true, even if every remaining subtype is NoReturn. Returning false immediately preserves the existing reachability result while avoiding unnecessary analysis of later union members.

Any reproducible mypy_primer diagnostic differences should be reviewed for correctness rather than treated as regressions solely because diagnostics changed.

The separate typeUtils helper optimization remains in #11681.

Validation

  • pnpm --dir packages/pyright-internal exec jest typeEvaluator1.test -t "Unreachable1" --forceExit
  • pnpm --dir packages/pyright-internal run build
  • pnpm exec prettier --check packages/pyright-internal/src/analyzer/codeFlowEngine.ts

@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/codeFlowEngine.ts
Comment thread packages/pyright-internal/src/tests/samples/unreachable1.py
@github-actions

This comment has been minimized.

if (isUnion(type)) {
return type.priv.subtypes.every((subtype) => {
callback(subtype);
return callback(subtype);

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.

every expects the return result from callback

const subtypeLiteralTypeName = getLiteralTypeClassName(subtype);
if (!subtypeLiteralTypeName) {
foundMismatch = true;
return undefined;

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.

use early exit

@github-actions

This comment has been minimized.

@bschnurr
Bill Schnurr (bschnurr) force-pushed the perf/no-return-unknown-guard branch from a98974d to 0e65014 Compare August 26, 2026 17:01
@rchiodo

Rich Chiodo (rchiodo) commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR.

@rchiodo

Copy link
Copy Markdown
Collaborator

Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) added the review-auto:approved Automated review: no blocking findings (approval posted). label Aug 26, 2026
@bschnurr
Bill Schnurr (bschnurr) force-pushed the perf/no-return-unknown-guard branch from 0e65014 to 618ec5f Compare August 26, 2026 17:14
@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@bschnurr
Bill Schnurr (bschnurr) force-pushed the perf/no-return-unknown-guard branch from 618ec5f to 25e1ec9 Compare August 26, 2026 17:21
@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

1 similar comment
@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@bschnurr
Bill Schnurr (bschnurr) force-pushed the perf/no-return-unknown-guard branch from 25e1ec9 to ae76d44 Compare August 26, 2026 17:27
@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@github-actions

This comment has been minimized.

@rchiodo

Copy link
Copy Markdown
Collaborator

Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified.

@github-actions

This comment has been minimized.

@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

Document that a union call target containing Any or Unknown does not make subsequent code unreachable.
@bschnurr
Bill Schnurr (bschnurr) force-pushed the perf/no-return-unknown-guard branch from ae76d44 to d9a9a3d Compare August 26, 2026 18:39
@bschnurr Bill Schnurr (bschnurr) changed the title Avoid NoReturn analysis for Any or Unknown calls Cover Any and Unknown call targets in NoReturn reachability Aug 26, 2026
@rchiodo

Copy link
Copy Markdown
Collaborator

Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified.

@github-actions

This comment has been minimized.

@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@github-actions

This comment has been minimized.

Stop scanning a callable union once Any or Unknown proves the call cannot be guaranteed to return NoReturn.
@bschnurr Bill Schnurr (bschnurr) changed the title Cover Any and Unknown call targets in NoReturn reachability Short-circuit NoReturn analysis for Any or Unknown calls Aug 27, 2026
@github-actions

This comment has been minimized.

@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

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

Labels

review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants