Skip to content

Allow object top type for covariant type vars with type bound in annotation context #19345

Closed as not planned
@sanderr

Description

@sanderr

Description & motivation

Allow widening type subscriptions for annotations beyond the type var bound, if the type var is covariant.

Consider the type Box[T: Boxable] (see example section below for more details), where T is covariant. The Boxable bound could be a union or some abstract type. The bound is typically relevant for the implementation of the class, or to constrain subclasses' concrete types. Essentially, for all concrete use cases, the bound is important.

However, type annotations are more of an abstract case. Considering that the type var is covariant, it should allow us to widen the bound. In a context that doesn't care about the specifics of what is allowed, or even a context that doesn't want to get involved with such details, it could be more readable (and still correct I believe) to generalize.

Specifically, I would be very interested in the ability to use the top type object to declare I don't care about which concrete instantiation of Box I get, and I'm in a context where I don't even care or want to get involved with which concrete types are allowed for T.

Example

type Boxable = int | str
"""
Concrete types that are supported in a box. Important for concrete, runtime cases, e.g. they must be serializable.
"""


class Box[T: Boxable]:
    """
    Immutable box for a value. Concrete boxes
    """
    def __init__(self, x: T) -> None:
        self.x = x

    def get(self) -> T:
        return self.x


# I don't care what box allows, I can print anything and I want to keep my interface simple.
def print_contents(box: Box[object]) -> None:
    """
    Print contents of a box.
    """
    print(box.get())

Mypy raises an error for the box: Box[object] annotation that 'Type argument "object" of "Box" must be a subtype of "int | str"'. I believe that this is too restrictive. As motivated in the comment above the function, this is a context where we don't care about Box's constraints or invariants. Only that it contains some object. In practice this will always be a Boxable, but this function doesn't need to know about that.

Notes

  • This feature request may be impossible at the moment, due to Use case for typing.Type with abstract types #4717 (comment).
  • In Python 3.13 I could probably get something close to what I describe in my example use case by using type var defaults. So that decreases the relevance, but even then I might occasionally want to express the simplified generalization object for readability purposes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions