fix `list.__add__` to use the expected type
originally: #14756
now broken (mypy)
_: list[int | str] = list[int]() + list[str]()
this break seems extremely minor (two cases in corpus)
now fixed (mypy)
_: list[int | str] = list[str]() + list[str | int]()
now fixed (pyright):
_: list[object] = list[int]() + list[str]()
Diff from mypy_primer, showing the effect of this PR on open source code:
zulip (https://github.com/zulip/zulip)
+ zerver/lib/onboarding_steps.py:65: error: Unsupported operand types for + ("list[OneTimeNotice]" and "list[OneTimeAction]") [operator]
prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/utilities/callables.py:579: error: Incompatible types in assignment (expression has type "list[None]", variable has type "list[Optional[expr]]") [assignment]
- src/prefect/utilities/callables.py:579: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- src/prefect/utilities/callables.py:579: note: Consider using "Sequence" instead, which is covariant
- src/prefect/utilities/callables.py:581: error: Unsupported operand types for + ("list[None]" and "list[Optional[expr]]") [operator]
pydantic (https://github.com/pydantic/pydantic)
- pydantic/aliases.py:29: error: Incompatible types in assignment (expression has type "list[str]", variable has type "list[int | str]") [assignment]
- pydantic/aliases.py:29: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- pydantic/aliases.py:29: note: Consider using "Sequence" instead, which is covariant
- pydantic/aliases.py:29: error: Argument 1 to "list" has incompatible type "tuple[str | int, ...]"; expected "Iterable[str]" [arg-type]
meson (https://github.com/mesonbuild/meson)
+ mesonbuild/modules/i18n.py:165:43: error: Unsupported operand types for + ("list[File]" and "list[CustomTarget]") [operator]
This has the same problem as #14755: _T1 has the same meaning as Any, so this is what we should use (with an appropriate comment). Also, the tests are not successful.
that's just not true, a type var and Any are different. if we make this Any then it will include Any, we don't want that
could you explain why you think it's Any? or respond to my example where I explain how they are different
One of your examples relied on an incorrect behavior in your type checker (assignability involving list[B] and list[A | Any]). Another involved a TypeVar with a default, which this one doesn't have.
One of your examples relied on an incorrect behavior in your type checker (assignability involving
list[B]andlist[A | Any]). Another involved a TypeVar with a default, which this one doesn't have.
yes, i already said the first example wasn't right, i've hidden it for clarity. the case with the deafult, is to explain the situation, but i can understand that it's not 1-to-1, so consider this:
def list_unsafe(*t: object) -> list[Any | int]:
if bool():
return ["oops", 1] # no error
else:
return [*t, 1]
unsafe1 = list_unsafe(None) # `unsafe1` is `list[Any | int]`
unsafe2 = list_unsafe() # `unsafe2` is `list[Any | int]`
def list_safe[T](*t: T) -> list[T | int]:
if bool():
return [1, "oops"] # error
else:
return [1, *t]
safe1 = list_safe(None) # `safe1` is `list[None | int]`
safe2 = list_safe() # `safe2` is `list[int]`
then we just remove the redundant unused *t and we get
def list_safe[T]() -> list[T | int]:
if bool():
return ["oops", 1] # error
else:
return [1]
safe1 = list_safe() # `safe1` is `list[int]`
safe2: list[object] = list_safe() # `safe2` is `list[object]`, with no error
Code sample in basedpyright playground
effectivly, T is inferred as Never in these cases and is collapsed against the int
but even if Any and a type var did have the same semantics here, it would still be a mistake to use Any. Any means "not typed", just because something has the same outcome, it should still be typed correctly. print is def print(*values: object, ... why not use Any here if it has the same meaning as object?
Diff from mypy_primer, showing the effect of this PR on open source code:
core (https://github.com/home-assistant/core)
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
zulip (https://github.com/zulip/zulip)
+ zerver/lib/onboarding_steps.py:65: error: Unsupported operand types for + ("list[OneTimeNotice]" and "list[OneTimeAction]") [operator]
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "SubTest" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "SubTest" defined here
ibis (https://github.com/ibis-project/ibis)
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "Any" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "Any" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "__init__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "__init__" of "object" defined here
prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/utilities/callables.py:579: error: Incompatible types in assignment (expression has type "list[None]", variable has type "list[Optional[expr]]") [assignment]
- src/prefect/utilities/callables.py:579: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- src/prefect/utilities/callables.py:579: note: Consider using "Sequence" instead, which is covariant
- src/prefect/utilities/callables.py:581: error: Unsupported operand types for + ("list[None]" and "list[Optional[expr]]") [operator]
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
pydantic (https://github.com/pydantic/pydantic)
- pydantic/aliases.py:29: error: Incompatible types in assignment (expression has type "list[str]", variable has type "list[int | str]") [assignment]
- pydantic/aliases.py:29: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- pydantic/aliases.py:29: note: Consider using "Sequence" instead, which is covariant
- pydantic/aliases.py:29: error: Argument 1 to "list" has incompatible type "tuple[str | int, ...]"; expected "Iterable[str]" [arg-type]
strawberry (https://github.com/strawberry-graphql/strawberry)
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
meson (https://github.com/mesonbuild/meson)
+ mesonbuild/modules/i18n.py:165:43: error: Unsupported operand types for + ("list[File]" and "list[CustomTarget]") [operator]
Diff from mypy_primer, showing the effect of this PR on open source code:
core (https://github.com/home-assistant/core)
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
zulip (https://github.com/zulip/zulip)
+ zerver/lib/onboarding_steps.py:65: error: Unsupported operand types for + ("list[OneTimeNotice]" and "list[OneTimeAction]") [operator]
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "SubTest" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "SubTest" defined here
ibis (https://github.com/ibis-project/ibis)
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "Any" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "Any" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:117: note: "__init__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:118: note: "__init__" of "object" defined here
prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/utilities/callables.py:579: error: Incompatible types in assignment (expression has type "list[None]", variable has type "list[Optional[expr]]") [assignment]
- src/prefect/utilities/callables.py:579: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- src/prefect/utilities/callables.py:579: note: Consider using "Sequence" instead, which is covariant
- src/prefect/utilities/callables.py:581: error: Unsupported operand types for + ("list[None]" and "list[Optional[expr]]") [operator]
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
pydantic (https://github.com/pydantic/pydantic)
- pydantic/aliases.py:29: error: Incompatible types in assignment (expression has type "list[str]", variable has type "list[int | str]") [assignment]
- pydantic/aliases.py:29: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
- pydantic/aliases.py:29: note: Consider using "Sequence" instead, which is covariant
- pydantic/aliases.py:29: error: Argument 1 to "list" has incompatible type "tuple[str | int, ...]"; expected "Iterable[str]" [arg-type]
strawberry (https://github.com/strawberry-graphql/strawberry)
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
- ...typeshed_to_test/stdlib/builtins.pyi:139: note: "__init_subclass__" of "object" defined here
+ ...typeshed_to_test/stdlib/builtins.pyi:140: note: "__init_subclass__" of "object" defined here
meson (https://github.com/mesonbuild/meson)
+ mesonbuild/modules/i18n.py:165:43: error: Unsupported operand types for + ("list[File]" and "list[CustomTarget]") [operator]