Skip to content

Fix incorrect type inference for nested unpacking with mixed star expr#21486

Closed
zons-zhaozhy wants to merge 2 commits into
python:masterfrom
zons-zhaozhy:fix/nested-unpack-inference
Closed

Fix incorrect type inference for nested unpacking with mixed star expr#21486
zons-zhaozhy wants to merge 2 commits into
python:masterfrom
zons-zhaozhy:fix/nested-unpack-inference

Conversation

@zons-zhaozhy
Copy link
Copy Markdown

Summary

Fixes #21485

When unpacking a list/tuple literal containing a star expression mixed with non-star items of different types, mypy incorrectly inferred the type of individual variables based on static position rather than considering that star expansion length is dynamic.

Example

from typing import reveal_type
text = "some\nstuff"
version, desc, *_ = [*text.split(sep="\n", maxsplit=1), None, None]
reveal_type(version)  # Before: str      After: str | None
reveal_type(desc)     # Before: None     After: str | None

Root Cause

In check_assignment_to_multiple_lvalues, when the rvalue is a list/tuple literal with a star expression, the code expands the star into TempNode(iterable_type) items and keeps non-star items as-is. It then pairs rvalues with lvalues by position.

The bug occurs when:

  1. The rvalue has a star expression followed by non-star items (e.g., [*xs, None, None])
  2. The lvalues have a star target (e.g., *_)
  3. Trailing non-star items in the rvalue end up paired with non-star lvalues before the star target

In this scenario, the trailing items positions are not fixed — they shift depending on the runtime length of the star expansion. The old code assigned them their literal types (e.g., None), missing that those positions could also hold items from the star (e.g., str).

Fix

The fix computes the number of excess trailing items — those that will be assigned to non-star lvalues before the star target — and replaces them (along with the star expansion items) with TempNode of the union type, ensuring correct inference.

The fix is targeted: it only applies when there is both a star in the rvalues AND a star in the lvalues, AND there are excess trailing items that would be assigned to non-star lvalues.

Test Plan

  • Added 3 test cases to check-lists.test:
    • testUnpackListWithMixedStarExprAndNone21485: the exact bug from the issue
    • testUnpackListWithStarExprAndMixedTypes21485: mixed int/str types
    • testUnpackListWithStarExprOnlyNoRegression21485: pure star expr (no regression)
  • Full test suite passes (11,775 tests in mypy/test/)

zzy-git and others added 2 commits May 15, 2026 01:58
When unpacking a list/tuple literal containing a star expression mixed
with non-star items of different types, mypy incorrectly inferred the
type of individual variables based on static position rather than
considering that star expansion length is dynamic.

Example:
    version, desc, *_ = [*text.split(), None, None]
    # Before: version: str, desc: None  (wrong)
    # After:  version: str | None, desc: str | None  (correct)

The fix only applies when:
1. The lvalues contain a star target (e.g., *_)
2. There are non-star rvalue items after the star expression
3. Those trailing items would be assigned to non-star lvalues
   before the star target (excess items)

In these cases, the fix computes the union of the star's element type
and the types of the excess trailing items, ensuring correct inference.

Closes python#21485
@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. ✅

@ilevkivskyi
Copy link
Copy Markdown
Member

We do not encourage LLM generated PRs from new contributors (our CONTRIBUTING.md will be updated soon to reflect this).

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.

wrong inference with nested unpacking

3 participants