Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with caching of equivalent but not identical generic types #559

Closed
mitar opened this issue May 9, 2018 · 3 comments
Closed

Issues with caching of equivalent but not identical generic types #559

mitar opened this issue May 9, 2018 · 3 comments

Comments

@mitar
Copy link
Contributor

mitar commented May 9, 2018

This is as expected:

>>> from typing import *
>>> Union[int, None] is Union[None, int]
False
>>> Union[int, None] == Union[None, int]
True

When order is not the same, types are equivalent, but not identical.

But, when used inside generic, then a surprise happens:

>>> from typing import *
>>> List[Union[int, None]] is List[Union[None, int]]
True
>>> List[Union[int, None]] == List[Union[None, int]]
True

The issue is that the first instance of List[Union[int, None]] is cached and returned for List[Union[None, int]] as well. So:

>>> from typing import *
>>> A = Union[int, None]
>>> B = Union[None, int]
>>> List[A]
typing.List[typing.Union[int, NoneType]]
>>> List[B]
typing.List[typing.Union[int, NoneType]]
>>> assert List[B].__args__[0] is B
AssertionError

I think caching should cache only identical generic types, not equivalent generic types.

In our case this is a problem because we inspect types and generate JSON description of types. And now it is happening that JSON descriptions are changing (because order of values in Union is changing) depending on the order of code loading and which generic type is loaded first during runtime.

@ilevkivskyi
Copy link
Member

I would say if your code depends on Union[str, int] and Union[int, str] being different, then there is something wrong with your code. It is standard to cache by __eq__/__hash__, I have never seen caching by is, also it is not something new, I believe types were cached like this since late 2016.

@mitar
Copy link
Contributor Author

mitar commented May 9, 2018

It is standard to cache by __eq__/__hash__

Sure, but then cache also Union[int, None], so that Union[int, None] is Union[None, int] equals True. I do not mind either way. But currently some types go one way and other types go another.

@gvanrossum
Copy link
Member

You should not count on the caching either way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants