Skip to content

Generic type parameters to Argument 1 of attrs.evolve only unify under very specific circumstances (mypy 1.2) #15088

Closed
@mwchase

Description

@mwchase

Bug Report

(A clear and concise description of what the bug is.)

To Reproduce

from __future__ import annotations

from attrs import evolve, frozen
from typing import Generic, TypeVar

T1 = TypeVar("T1")
T2 = TypeVar("T2")


@frozen
class Test(Generic[T1]):
    var: T1

    # Can't substitute equivalent typevar in method.
    def update(self: Test[T2], var: T2) -> Test[T2]:
        return evolve(self, var=var)


# Can't use *same* typevar in function.
def update_t1(test: Test[T1], var: T1) -> Test[T1]:
    return evolve(test, var=var)


# Can't use equivalent typevar in function.
def update_t2(test: Test[T2], var: T2) -> Test[T2]:
    return evolve(test, var=var)

Actual Behavior

test_mypy.py:16: error: Argument 1 to "evolve" of "Test[T2]" has incompatible type "Test[T2]"; expected "Test[T1]"  [arg-type]
test_mypy.py:16: error: Argument "var" to "evolve" of "Test[T2]" has incompatible type "T2"; expected "T1"  [arg-type]
test_mypy.py:21: error: Argument 1 to "evolve" of "Test[T1]" has incompatible type "Test[T1]"; expected "Test[T1]"  [arg-type]
test_mypy.py:21: error: Argument "var" to "evolve" of "Test[T1]" has incompatible type "T1"; expected "T1"  [arg-type]
test_mypy.py:26: error: Argument 1 to "evolve" of "Test[T2]" has incompatible type "Test[T2]"; expected "Test[T1]"  [arg-type]
test_mypy.py:26: error: Argument "var" to "evolve" of "Test[T2]" has incompatible type "T2"; expected "T1"  [arg-type]
Found 6 errors in 1 file (checked 1 source file)

This gets worse when using constrained typevars, because the typevar on the function/method gets expanded to every constraint, but the typevar on the class isn't expanded, so it only accepts the typevar, even though it's passing the concrete type.

Your Environment

  • Mypy version used: mypy 1.2.0 (compiled: yes) (passes with mypy 1.1.1 (compiled: yes))
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files): (these approximate some past version of --strict, and a bunch of project-specific stuff that shouldn't be relevant)
[mypy]
warn_unused_configs = True
disallow_any_generics = True
disallow_subclassing_any = True
disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_untyped_decorators = True
no_implicit_optional = True
warn_redundant_casts = True
warn_unused_ignores = True
warn_return_any = True
no_implicit_reexport = True
strict_equality = True

plugins = trio_typing.plugin, plugins/type_func.py
show_error_codes = True

mypy_path = $MYPY_CONFIG_FILE_DIR/stubs

[mypy-cement.utils.version]
ignore_missing_imports = True

[mypy-cement.core.exc]
ignore_missing_imports = True

[mypy-tqdm]
ignore_missing_imports = True
  • Python version used: 3.9.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions