Skip to content

Incorrect types inferred when a "mixed tuple" is unpacked #947

@AlexWaygood

Description

@AlexWaygood

Summary

Consider:

class I0: ...
class I1: ...
class I2: ...

def f(x: tuple[I0, *tuple[I1, ...], I2]):
    [a, b, *c] = x
    reveal_type(a)  # I0
    reveal_type(b)  # I1
    reveal_type(c)  # list[I1 | I2]

The types we infer for a and c seem correct here. But the type for b seems incorrect. There are three possible scenarios in which this assignment could succeed; I think we need to consider them all and union the types together:

  1. The middle element "materialises" to a 0-length tuple. In this scenario at runtime, a would be of type I0, b would be of type I2 and c would be of type list[Never]
  2. The middle element "materialises" to a tuple of length 1. In this scenario at runtime, a would be of type I0, b would be of type I1 and c would be of type list[I2]
  3. The middle element "materialises" to a tuple of length >=2. In this scenario at runtime, a would be of type I0, b would be of type I1 and c would be of type list[I1 | I2]

Given these three scenarios in which the assignment could succeed, I think we should be inferring I1 | I2 for b rather than I1.

Version

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions