Maxinho96 · GitHub

Bug report

Bug description:

https://gist.github.com/devdanzin/3198710e3c0128fda5e0a7b4e0768e5f#5-literal-deduplication-silently-skips-when-values-are-unhashable

Findings

The issue text is wrong: the unhashable_fallback param is not used in Annotated or anywhere else.
The parameter was added and actively used in commit a7549b0 (gh-112281 / PR #112283, Mar 2024).
In that revision, Union dedup went through _remove_dups_flatten, which called _deduplicate with unhashable_fallback=True to handle unhashable metadata.

Why it is not used now:
In commit dc6d66f (gh-105499 / PR #105511, Mar 2025), typing.Union was merged with types.UnionType.
That rewrite removed the old Python-side Union construction path in typing.py (including _remove_dups_flatten and the old Union special-form machinery), so the only known caller of unhashable_fallback=True disappeared.
Today, _deduplicate still has the keyword parameter, but the remaining in-file call path (Literal handling) does not pass it.

I tried to just pass the argument, but then this existing test fails, which has this comment:

# Mutable arguments will not be deduplicated

The test was added with commit f03d318 , when deduplication of Literals was first introduced. From the commit, it looks like excluding unhashable params from deduplication was the intended behavior.

Proposal

I propose to use the unhashable_fallback param anyway, and change the failing test, since the intended behavior doesn't seem right to me as of today: I think Literal should always deduplicate, even when the params are unhashable.

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Read the original on github.com ↗