Pyright: Aliasing generic type containing typevar doesn't work

Created on 6 Jan 2021  路  4Comments  路  Source: microsoft/pyright

Describe the bug

from typing import List, TypeVar

T = TypeVar("T")
L = List[T]

def f(x: L) -> L:
    ...

f([1, 2, 3]) # Error

Outputs:

  11:3 - error: Argument of type "list[int]" cannot be assigned to parameter "x" of type "L[T@L]" in function "f"
  聽聽TypeVar "_T@list" is invariant
  聽聽聽聽Type "int" cannot be assigned to type "T@L" (reportGeneralTypeIssues)

It works if the alias L is not used:

from typing import List, TypeVar

T = TypeVar("T")


def f(x: List[T]) -> List[T]: # not use alias `L`
    ...


f([1, 2, 3]) # OK

This problem also occurs for covariant container type:

from typing import List, TypeVar, FrozenSet

T = TypeVar("T")
L = FrozenSet[T] # Use FrozenSet (covariant type) insead of List

def f(x: L) -> L:
    ...
f(frozenset([1, 2, 3]))  # Error

Mypy doesn't output any error.

Expected behavior

No error

Additional context

pyright: 1.1.99

addressed in next version bug

All 4 comments

Pyright is doing the right thing here. You're defining a generic type alias L that takes a single type argument, but then you're failing to provide a type argument for it when you use it.

The following is a correct usage of a generic type alias L:

def f(x: L[T]) -> L[T]:
    ...

Arguably, Pyright should provide an error when you attempt to use L without any type arguments (since it is defined such that it requires a single type argument). I'll look into adding that error.

There was already code in place that was supposed to emit an error when a generic type alias was used without any type arguments provided, but there was a bug in this code. I've fixed that bug. Here's how it looks with that fix in place:

Screen Shot 2021-01-06 at 7 34 46 AM

Thanks!!

This is fixed in Pyright 1.1.100, which I just published. It will also be included in the next release of Pylance.

Was this page helpful?
0 / 5 - 0 ratings