Skip to content

CovariantClass[T | U] should be assignable to CovariantClass[T] | CovariantClass[U] #1308

@AlexWaygood

Description

@AlexWaygood

Summary

On main we have this behaviour:

from typing import reveal_type
from ty_extensions import is_subtype_of

class Covariant[T]:
    def get(self) -> T:
        raise NotImplementedError

# revealed: `ConstraintSet[never]`
reveal_type(is_subtype_of(Covariant[int | str], Covariant[str] | Covariant[int]))

This is incorrect: due to covariance, the types Covariant[int | str] and Covariant[str] | Covariant[int] are actually equivalent types.

Possibly we could fix this by ensuring that (for covariant and bivariant types) we always eagerly explode unions when creating specialized generics. So, similar to the way the type T & (U | V) can never exist in our type representation (we would always represent the type as (T & U) | (T & V), we would never permit the type Covariant[int | str] to exist in our internal representation (it would always be represented internally as Covariant[str] | Covariant[int]).

The same issue exists for tuples (#493 tracks that)

Version

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtype propertiessubtyping, assignability, equivalence, and more

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions