runtype icon indicating copy to clipboard operation
runtype copied to clipboard

runtype does not respect transitivity of subtyping relation between MutableMapping and Mapping

Open 27359794 opened this issue 1 month ago • 1 comments

(Pdb) runtype.issubclass(typing.MutableMapping[str, int], typing.Mapping[str, int])
True
(Pdb) runtype.issubclass(typing.Mapping[str, int], typing.Mapping[str, int | str])
True
(Pdb) runtype.issubclass(typing.MutableMapping[str, int], typing.Mapping[str, int | str])
False

By transitivity of subtype relation, if the first two expressions hold, then the third must hold as well. But according to the library, the third expression is False.

Environment: Python 3.12, runtype version 0.5.3

27359794 avatar Dec 03 '25 21:12 27359794

Thank you for reporting.

As a goal, I'm trying to align runtype's behavior with the official type hint system (i.e. mypy and such).

Here's what PEP 0484 says about this:

By default generic types are considered invariant in all type variables, which means that values for variables annotated with types like List[Employee] must exactly match the type annotation – no subclasses or superclasses of the type parameter (in this example Employee) are allowed.

The mutable collection classes (e.g. MutableMapping and MutableSequence) are declared invariant.

So while there's a lot of sense in your expectation of transitivity, in this case it would go against the Python spec!

But I'm open to new opinions on the matter.

TL;DR - while not intuitive, I think this is the correct behavior.

erezsh avatar Dec 03 '25 22:12 erezsh