Skip to content

Fix list concatenation ignoring outer list type context#21746

Open
Ria-K912 wants to merge 5 commits into
python:masterfrom
Ria-K912:fix-list-concat-type-context
Open

Fix list concatenation ignoring outer list type context#21746
Ria-K912 wants to merge 5 commits into
python:masterfrom
Ria-K912:fix-list-concat-type-context

Conversation

@Ria-K912

Copy link
Copy Markdown

Fixes #21710

List literals already use an outer list[...] type context for bidirectional inference, so this works:

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

But concatenation did not forward that context, so both operands were inferred as list[int] and assignment failed due to invariance:

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

This PR special-cases + when the active type context is builtins.list, similar to the existing [...] * n handling: both operands are checked under that context before list.__add__ is applied. That covers list literals, list comprehensions, empty lists, and chained +.

Added testListAddInContext. Invalid cases still error, e.g. y: list[int] = [0] + ["x"].

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@Ria-K912
Ria-K912 force-pushed the fix-list-concat-type-context branch from c690ee7 to d619ba7 Compare July 18, 2026 07:31
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@Ria-K912

Copy link
Copy Markdown
Author

Re #21755 point-by-point:

Impact claims

  1. “Patch will not parse cleanly” - False. No conflict markers; CI is green.
  2. “Unresolved merge conflict markers” - False. Diff has none (<<<<<<< / ======= / >>>>>>>).
  3. x = a + [10] doesn’t exercise the bug” - Incomplete. That line is a secondary case; the List constant expression treated differently to list literal #21710 bug is covered by x = [0, 1, 2] + [10] and the comprehension case.
  4. “P3 nested lists has no coverage” - Chained + is tested ([1] + [2] + [3]). Nested list[list[T]] was never claimed for this fix.
  5. “P1/P2 depend on mangled check_op_expr” -False. No mangled code; change is a clean check_list_add when context is builtins.list.
  6. “Failing-first violated” -Tests cover the intended behavior, including a negative case (y = [0] + ['x']).
  7. “Verify the test exercises the bug” - Already done via the literal/comprehension cases above.

@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/utilities/callables/__init__.py:717: error: Incompatible types in assignment (expression has type "list[None]", variable has type "list[expr | None]")  [assignment]
- src/prefect/utilities/callables/__init__.py:717: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- src/prefect/utilities/callables/__init__.py:717: note: Consider using "Sequence" instead, which is covariant
- src/prefect/utilities/callables/__init__.py:719: error: Unsupported operand types for + ("list[None]" and "list[expr | None]")  [operator]

pydantic (https://github.com/pydantic/pydantic)
- pydantic/aliases.py:28: error: Incompatible types in assignment (expression has type "list[str]", variable has type "list[int | str]")  [assignment]
- pydantic/aliases.py:28: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- pydantic/aliases.py:28: note: Consider using "Sequence" instead, which is covariant
- pydantic/aliases.py:28: error: Argument 1 to "list" has incompatible type "tuple[str | int, ...]"; expected "Iterable[str]"  [arg-type]

dedupe (https://github.com/dedupeio/dedupe)
+ dedupe/labeler.py:451: error: Unused "type: ignore" comment  [unused-ignore]
+ dedupe/labeler.py:487: error: Unused "type: ignore" comment  [unused-ignore]

jax (https://github.com/google/jax)
- jax/_src/numpy/lax_numpy.py:3148: error: Incompatible types in assignment (expression has type "list[int]", variable has type "list[float64]")  [assignment]
+ jax/_src/numpy/lax_numpy.py:3148: error: List item 0 has incompatible type "int"; expected "float64"  [list-item]

@Ria-K912

Ria-K912 commented Jul 20, 2026

Copy link
Copy Markdown
Author

@hauntsaninja, @JelleZijlstra Could you please take a look at this PR? It fixes #21710 by forwarding outer list[...] context through list + (only for list constructors).

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.

List constant expression treated differently to list literal

1 participant