At this point, pyright complains with # error: Operator "|" not supported for types "dict[str, int]" and "Mapping[str, int]".
I referenced this problem in this issue. Thanks.
That would be incorrect, however, because not all mappings can be merged with a dict using the | operator: it's not part of the collections.abc.Mapping interface. We used to define dict.__or__ in the way you propose above, but we changed it after a user complained that their type checker failed to spot a bug in their code. See #10678 and #10679.
I don't understand what you mean with it's not part of the Mapping interface. dict | Mapping -> dict and this can be guaranteed regardless of the concrete mapping instance. And Mapping | dict -> ? because the concrete implementation of Mapping will take precedence over the dict.__ror__ method. Am I wrong?
I was proposing a change on the __or__ method, not on the __ror__ method. Thanks and let me know if I overlooked something.
Activity
AlexWaygood commented on Jan 9, 2024
That would be incorrect, however, because not all mappings can be merged with a dict using the | operator: it's not part of the collections.abc.Mapping interface. We used to define dict.__or__ in the way you propose above, but we changed it after a user complained that their type checker failed to spot a bug in their code. See #10678 and #10679.
jzazo commented on Jan 9, 2024
I don't understand what you mean with it's not part of the Mapping interface. dict | Mapping -> dict and this can be guaranteed regardless of the concrete mapping instance. And Mapping | dict -> ? because the concrete implementation of Mapping will take precedence over the dict.__ror__ method. Am I wrong?
I was proposing a change on the __or__ method, not on the __ror__ method. Thanks and let me know if I overlooked something.
srittau commented on Jan 10, 2024
As pointed out by Alex in #10678, dict.__or__ explicitly checks whether the other object is a dict:
https://github.com/python/cpython/blob/5d384b0468b35b393f8ae2d3149d13ff607c9501/Objects/dictobject.c#L3713C1-L3728
The following code fails at runtime:
Traceback (most recent call last): File "foo.py", line 11, in <module> {} | MyMapping() ~~~^~~~~~~~~~~~~ TypeError: unsupported operand type(s) for |: 'dict' and 'MyMapping'jzazo commented on Jan 10, 2024
Thanks @srittau for explaining.
JelleZijlstra commented on Jan 10, 2024
And just in case you were looking for a workaround {"b": 2, **a} works on any Mapping and should be accepted by type checkers.