Skip to content

List constant expression treated differently to list literal #21710

Description

@bmerry

Bug Report

When assigning a list literal to a variable with a known type, mypy uses that type in inferring the type of the list literal. This gives the appearance that invariance is relaxed e.g.

x: list[int | None] = [0, 1, 2, 10]  # ok

is accepted even though normally a list[int] cannot be assigned to a list[int | None].

However, when the list literal is written as a more complex expression, that stops working:

x: list[int | None] = [0, 1, 2] + [10]  # error

That's obviously a bit contrived. My actual use case is more similar to this:

x: list[int | None] = [i for i in range(3)] + [10]  # error

Maybe this isn't fixable - it's only sound because list.__add__ returns a new list which has no other references, but I don't think there is a way to represent that in typeshed.

To Reproduce

x: list[int | None] = [0, 1, 2] + [10]

Expected Behavior

No error

Actual Behavior

concat2.py:1: error: Incompatible types in assignment (expression has type "list[int]", variable has type "list[int | None]")  [assignment]
concat2.py:1: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
concat2.py:1: note: Consider using "Sequence" instead, which is covariant

Your Environment

  • Mypy version used: 2.2.0
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.12.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions