python / python/cpython

`isinstance(obj, Hashable)` raises `TypeError` when both `obj` and `type(obj)` are unhashable

Ouverte
#129,589 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

extension-modules type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Bug report

Bug description:

Assumption: isinstance(anything, any_type) should never raise.

The problem appears to be in _abc.c function _abc__abc_subclasscheck_impl (known at runtime as _abc._abc_subclasscheck()), which reads (in part):

    /* 1. Check cache. */
    incache = _in_weak_set(impl->_abc_cache, subclass);

The implementation assumes subclass is hashable. That's almost always true of classes, but not guaranteed.

Reproduction case:

from __future__ import annotations
from collections.abc import Hashable

class UnhashableMeta(type):
    def __eq__(self, other: object) -> bool:
        return super().__eq__(other)

class UnhashableClass(metaclass=UnhashableMeta):
    def __eq__(self, other: object) -> bool:
        return super().__eq__(other)

# any non-hashable instance of a non-hashable class
#         ┌────────┴────────┐
isinstance(UnhashableClass(), Hashable)

Traceback for (cpython) Python 3.13.1:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File ".../bug.py", line 14, in <module>
    isinstance(UnhashableClass(), Hashable)
    ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen abc>", line 119, in __instancecheck__
  File "<frozen abc>", line 123, in __subclasscheck__
TypeError: unhashable type: 'UnhashableMeta'

Tracebacks are nearly identical with Python 3.8, 3.9, 3.10, 3.11, and 3.12, as well as Python 3.14.0a4.

CPython versions tested on:

3.13, 3.12, 3.11, 3.10, 3.9, 3.14

Operating systems tested on:

macOS

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Ouvrez Modules/_abc.c et commencez par _abc__abc_subclasscheck_impl, plus précisément par l’appel à _in_weak_set décrit dans l’issue. Exécutez sur CPython la reproduction fournie avec UnhashableMeta et UnhashableClass, puis vérifiez que isinstance(UnhashableClass(), Hashable) ne lève plus d’exception et que la régression est couverte par un test approprié.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
c, python
Domaine
backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.