Skip to content

set.discard() swallows TypeError raised by __eq__; set.remove() replaces it with KeyError #155102

Description

@BHUVANSH855

Bug report

Bug description:

Bug description

When a hashable subclass of set is used as the lookup key, set.discard() silently swallows a TypeError raised from __eq__, while set.remove() replaces the original exception with KeyError.

The issue can be reproduced on current main.

Minimal reproducer

class Bad:
    def __hash__(self):
        return 1

    def __eq__(self, other):
        raise TypeError("boom from __eq__")


class HashableSet(set):
    def __hash__(self):
        return 1


s = {Bad()}
probe = HashableSet()

print("membership:")
try:
    probe in s
except Exception as exc:
    print(type(exc).__name__, exc)

print("\ndiscard:")
try:
    s.discard(probe)
except Exception as exc:
    print(type(exc).__name__, exc)
else:
    print("returned normally")

print("\nremove:")
try:
    s.remove(probe)
except Exception as exc:
    print(type(exc).__name__, exc)

Actual behavior

membership:
TypeError boom from __eq__

discard:
returned normally

remove:
KeyError HashableSet()

Expected behavior

The original exception raised from __eq__ should propagate consistently.

TypeError: boom from __eq__

should be raised by both set.discard() and set.remove(), just as it is during the corresponding membership test.

Additional investigation

I reproduced this on current main.

For debugging, I temporarily instrumented set_remove_impl() and set_discard_impl() immediately before their PyErr_Clear() calls. At that point, the active exception is still:

TypeError('boom from __eq__')

indicating that the original exception raised by __eq__ reaches those sites before being cleared.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions