Skip to content

Consider not treating Hashable as equivalent to object  #1162

@AlexWaygood

Description

@AlexWaygood

In astral-sh/ruff#20284, we reworked our logic so that Hashable is treated equivalently to object in subtyping and assignability checks. This is defensible from a theoretical perspective, since all instances of "exactly object" are hashable at runtime, which therefore makes object a subtype of Hashable by all normal rules of protocol assignability and subtyping. However, rules around hashability in Python do not obey the normal rules: hashable classes often inherit from unhashable ones, and unhashable classes often inherit from hashable ones, flying in the face of the Liskov Substitution Principle. Our current approach to Hashable and similar protocols makes these protocols effectively useless; we will not complain about code like this, even though users would expect us to do so (and even though other type checkers issue complaints):

from typing import Hashable

def f(x: Hashable): ...

f([])

Given that the Liskov principle is so frequently and fragrantly violated for hashability, in Python's builtin types, standard library, and across a wide range of Python code, it may be worth us seeing if we can roll back astral-sh/ruff#20284 and find another solution to #1132 that improves our compatibility with other type checkers. The reason why other type checkers do not run into problems such as #1132 is that they do not eagerly simplify unions of Hashable and other types in the same way we do. We should consider doing the same; it would probably lead to more intuitive behaviour from users' perspective, and compatibility with other type checkers is also a useful goal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Protocolsconformanceneeds-decisionAwaiting a decision from a maintainerset-theoretic typesunions, intersections and morewishNot on the current roadmap; maybe in the future

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions