Skip to content

Certain multiple inheritance using generic alias errors in 3.13 #112903

Closed

Description

@rmartin16

Bug report

Bug description:

Below is a simplification of some classes that create the problem:

import typing

K = typing.TypeVar("K")
V = typing.TypeVar("V")

class BaseMap(typing.Mapping[K, V]): ...

class MutableMap(BaseMap[K, V], typing.MutableMapping[K, V]): ...

class MyMap(typing.Dict[K, V], MutableMap[K, V]): ...

Just entering these definitions in the REPL causes the error.

The stack trace (with info about variable b):

b=__main__.MutableMap[~V]
type(b)=<class 'types.GenericAlias'>

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    class MyMap(typing.Dict[K, V], MutableMap[V]): ...
  File "/home/russell/.pyenv/versions/3.13-dev/lib/python3.13/typing.py", line 1391, in __mro_entries__
    return super().__mro_entries__(bases)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
  File "/home/russell/.pyenv/versions/3.13-dev/lib/python3.13/typing.py", line 1143, in __mro_entries__
    if isinstance(b, _BaseGenericAlias) or issubclass(b, Generic):
                                           ~~~~~~~~~~^^^^^^^^^^^^
TypeError: issubclass() arg 1 must be a class

This works "fine" before Python 3.13. If I swap the order of typing.Dict[K, V], MutableMap[V], the error no longer presents on 3.13.

I don't understand enough of intersection of these topics to know if this is now an expected error or something is considered wrong. This does seem related to #103369.

CPython versions tested on:

3.8, 3.9, 3.10, 3.11, 3.12, 3.13, CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. AlexWaygood commented on Feb 7, 2024

    @AlexWaygood
    Member

    @serhiy-storchaka, since the direct cause here was #103369 — do you have any opinions on this issue or the proposed fix?

  2. encukou commented on Feb 8, 2024

    @encukou
    Member

    What's the best way to get the attention of typing-sig experts?
    I can help, but I feel that I'd first need to become a typing expert myself -- a significant investment :)

  3. AlexWaygood commented on Feb 8, 2024

    @AlexWaygood
    Member

    I think all the people with relevant expertise on this area of code are already subscribed to this issue :) I'd say the active core devs who know this code best at this point are probably Jelle, me, Nikita and Serhiy. @carljm might also have some insight, though!

  4. AlexWaygood commented on Feb 8, 2024

    @AlexWaygood
    Member

    I can help, but I feel that I'd first need to become a typing expert myself -- a significant investment :)

    FWIW, this issue doesn't have much to do with the intricacies of static typing (so most typing-sig experts won't have much to say on it), but it has everything to do with the mechanisms we use to achieve the runtime implementation of typing. https://docs.python.org/3/reference/datamodel.html#object.__mro_entries__, and the references listed at the bottom of the docs for that method, would be the relevant reading required to understand what's going on here, if you are interested in helping :)

    The difference between typing._GenericAlias and types.GenericAlias comes down to whether a generic alias is created by machinery internal to the typing module or a builtin PEP-585 alias from outside the typing module

  5. serhiy-storchaka commented on Feb 8, 2024

    @serhiy-storchaka
    Member

    Does it work with dict, collections.abc.Mapping and collections.abc.MutableMapping instead of typing.Dict, typing.Mapping and typing.MutableMapping? Does it work with mixed types?

  6. serhiy-storchaka commented on Feb 8, 2024

    @serhiy-storchaka
    Member

    It is weird. It fails for b = MutableMap, but issubclass(MutableMap, typing.Generic) does not fail, and isinstance(MutableMap, typing.GenericAlias) returns False, so the proposed fix should not work.

  7. serhiy-storchaka commented on Feb 8, 2024

    @serhiy-storchaka
    Member

    Ah, it is MutableMap[K, V], not MutableMap.

    Interesting, typing.Mapping[K, V]) has type typing._GenericAlias, typing.MutableMapping[K, V]) has type typing._GenericAlias, but BaseMap[K, V] has type types.GenericAlias.

    The simpler way to reproduce the issue is:

    import typing
    T = typing.TypeVar("T")
    class A(typing.Iterable[T], list[T]): ...
  8. serhiy-storchaka commented on Feb 8, 2024

    @serhiy-storchaka
    Member

    Other, even simpler, example:

    import typing
    class A(typing.Sized, list[int]): ...
  9. JelleZijlstra commented on Feb 8, 2024

    @JelleZijlstra
    Member

    Thanks @serhiy-storchaka for the simpler examples. They helped me find that the proposed fix is wrong; I commented on the PR.

    I think to fix this issue we need to either revert #103369, or add special handling to issubclass() calls in typing.py so they deal with GenericAlias correctly.

  10. carljm commented on Feb 8, 2024

    @carljm
    Member

    We have clearly established for a while now that generic aliases are not types; they have __mro_entries__ so they can be inherited, but otherwise they do not pretend to be types. I don't think we can (or should) backtrack on this position; background on it can be found in #89828. Reverting #103369 is just a very small partial rollback of this position, which just leaves us in an inconsistent state.

    I do think the issubclass call in _BaseGenericAlias.__mro_entries__() is simply buggy as written, and must be protected by a prior isinstance(b, type) check. I put more details of that analysis into a comment on the PR.

  11. added 2 commits that reference this issue on Feb 9, 2024
  12. AlexWaygood commented on Feb 9, 2024

    @AlexWaygood
    Member

    Thanks again @rmartin16 for the early testing, thanks @encukou for bumping the issue (which I'd completely forgotten about!), and thanks @carljm for coming up with a fix!

  13. added a commit that references this issue on Feb 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

3.13only security fixesrelease-blockerstdlibStandard Library Python modules in the Lib/ directorytopic-typingtype-bugAn unexpected behavior, bug, or error

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions