Skip to content

Fix type evaluation of generator expressions inside contextually typed list/set literals (#11841) - #11895

Closed
Peter Hayes (HTMLPETE) wants to merge 1 commit into
microsoft:mainfrom
HTMLPETE:fix/list-set-generator-comprehension-11841
Closed

Peter Hayes (HTMLPETE) wants to merge 1 commit into
microsoft:mainfrom
HTMLPETE:fix/list-set-generator-comprehension-11841

Conversation

@HTMLPETE

Copy link
Copy Markdown

Summary

Addresses #11841.

When evaluating list or set entries against a contextual expected type (e.g. a: list[int] = [1, 2, (i for i in range(4))]), Pyright treated all ParseNodeType.Comprehension entries as sequence comprehensions, evaluating their yield element against the container element type.

However, a parenthesized generator expression inside a list literal is parsed as a Comprehension AST node with isGenerator === true. At runtime, its evaluated value is an instance of types.GeneratorType (Generator[T, None, None]), not an unpacked sequence of T.

This change adds a check for !entry.d.isGenerator in typeEvaluator.ts before delegating to getElementTypeFromComprehension. Generator expressions are thus evaluated through standard expression typing as Generator instances, correctly diagnosing type incompatibilities against declared collection element types.

Changes

  • packages/pyright-internal/src/analyzer/typeEvaluator.ts: Guard entry.nodeType === ParseNodeType.Comprehension with && !entry.d.isGenerator during contextual list entry evaluation.
  • packages/pyright-internal/src/tests/samples/list1.py: Added regression test case for generator expressions inside typed list literals.
  • packages/pyright-internal/src/tests/typeEvaluator6.test.ts: Updated diagnostic expectation count from 3 to 4.

Validation

  • Rebased cleanly on latest upstream/main.
  • npx jest src/tests/typeEvaluator6.test.ts passed: 169/169 tests passing (including List1).
  • npx prettier -c passed on all modified files with zero formatting discrepancies.

…d list/set literals (microsoft#11841)

When evaluating list entries against an expected type, Pyright treated all Comprehension nodes as list comprehensions whose elements must match the expected list element type. However, a parenthesized generator expression inside a list literal (e.g. [1, 2, (i for i in range(4))]) is parsed as a Comprehension node with isGenerator === true.

Because its runtime type is Generator[T, None, None], it should not be treated as an unpackable sequence or have its yield type extracted directly. This fix checks !entry.d.isGenerator before treating the node as a comprehension element, ensuring the expression is properly typed as a Generator and flagged if incompatible with the expected list element type.

Fixes microsoft#11841.

Signed-off-by: Peter Hayes <peter@ribbsaetersystems.com>
@HTMLPETE

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@heejaechang

Copy link
Copy Markdown
Collaborator

🟢 Pyright CLI QA — de973572 — verdict: green

Automated CLI checks compared this change with its base revision.
8 focused check(s) completed.

No new behavior difference was detected.

@bschnurr

Copy link
Copy Markdown
Member

/benchmark

@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. ✅

@rchiodo

Copy link
Copy Markdown
Collaborator

Thanks for the fix. I'm closing this in favor of #11889, which was opened first and has the identical patch, including regression coverage.

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.

4 participants