classification
Title: It is possible to create a 1-type union type
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.11, Python 3.10
process
Status: closed Resolution: fixed
Dependencies: 44632 Superseder:
Assigned To: Nosy List: gvanrossum, kj, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2021-07-14 11:04 by serhiy.storchaka, last changed 2021-07-16 11:49 by serhiy.storchaka. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 27178 merged serhiy.storchaka, 2021-07-16 06:44
PR 27181 merged serhiy.storchaka, 2021-07-16 09:52
Messages (7)
msg397476 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-07-14 11:04
typing.Union always collapsed to a simple type if it contains a single type.

>>> import typing
>>> typing.Union[int, typing.T][int]
<class 'int'>

But the builtin union type can contain a single type:

>>> (int | typing.T)[int]
int
>>> type((int | typing.T)[int])
<class 'types.Union'>
msg397527 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-07-15 07:44
Simple example (without indexing):

>>> import typing
>>> typing.Union[int, int]
<class 'int'>
>>> int | int
int
msg397559 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2021-07-15 15:17
I feel that keeping the singleton is more consistent. This normalization seems to me an example of the typing module doing too much. Singleton tuples are different from scalar values too.
msg397564 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-07-15 16:20
It is a difference with typing.Union which can cause confusion. If the union type is like a tuple and we leave a 1-type union, why do we bother with deduplication? Why int | str | int is collapsed into int | str?

Also it complicates the comparison implementation and produces surprising exceptions:

>>> int | str == {}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

Also it breaks one of fundamental properties -- equal objects should have equal hashes.

>>> (int | int) == int
True
>>> hash(int | int) == hash(int)
False
msg397577 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2021-07-15 19:57
Hm, you are right. Make it so, Mr. Spock! :-)
msg397608 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-07-16 09:49
New changeset d9f923280f204204f8703756aef4f655b579b4b8 by Serhiy Storchaka in branch 'main':
bpo-44636: Collapse union of equal types (GH-27178)
https://github.com/python/cpython/commit/d9f923280f204204f8703756aef4f655b579b4b8
msg397615 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-07-16 11:48
New changeset c3007ab3c6cb384203bac8aa64d89c4b42f671a1 by Serhiy Storchaka in branch '3.10':
[3.10] bpo-44636: Collapse union of equal types (GH-27178) (GH-27181)
https://github.com/python/cpython/commit/c3007ab3c6cb384203bac8aa64d89c4b42f671a1
History
Date User Action Args
2021-07-16 11:49:32serhiy.storchakasetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2021-07-16 11:48:23serhiy.storchakasetmessages: + msg397615
2021-07-16 09:52:46serhiy.storchakasetpull_requests: + pull_request25718
2021-07-16 09:49:40serhiy.storchakasetmessages: + msg397608
2021-07-16 06:44:18serhiy.storchakasetkeywords: + patch
stage: patch review
pull_requests: + pull_request25715
2021-07-15 19:57:15gvanrossumsetmessages: + msg397577
2021-07-15 16:20:01serhiy.storchakasetmessages: + msg397564
2021-07-15 15:17:35gvanrossumsetmessages: + msg397559
2021-07-15 07:44:41serhiy.storchakasetmessages: + msg397527
2021-07-14 11:05:14serhiy.storchakasetdependencies: + Union with TypeVar does not work as intended
2021-07-14 11:04:42serhiy.storchakacreate