diff --git a/tests/test_type_eval.py b/tests/test_type_eval.py index dcb0168..c7b2933 100644 --- a/tests/test_type_eval.py +++ b/tests/test_type_eval.py @@ -732,6 +732,10 @@ def test_eval_literal_idempotent_01(): t = nt +def test_is_literal_true_vs_one(): + assert eval_typing(Is[Literal[True], Literal[1]]) is False + + def test_callable_to_signature(): from typemap.type_eval._eval_operators import _callable_type_to_signature from typemap.typing import Param diff --git a/typemap/type_eval/_subsim.py b/typemap/type_eval/_subsim.py index 5e965d3..0c684c4 100644 --- a/typemap/type_eval/_subsim.py +++ b/typemap/type_eval/_subsim.py @@ -1,9 +1,7 @@ import typing - from . import _typing_inspect - __all__ = ("issubsimilar",) @@ -38,11 +36,11 @@ def issubsimilar(lhs: typing.Any, rhs: typing.Any) -> bool: return issubclass(lhs, rhs) # literal <:? literal - elif bool( - _typing_inspect.is_literal(lhs) and _typing_inspect.is_literal(rhs) - ): - rhs_args = set(typing.get_args(rhs)) - return all(lv in rhs_args for lv in typing.get_args(lhs)) + elif _typing_inspect.is_literal(lhs) and _typing_inspect.is_literal(rhs): + # We need to check both value and type, since True == 1 but + # Literal[True] should not be a subtype of Literal[1] + rhs_args = {(t, type(t)) for t in typing.get_args(rhs)} + return all((lv, type(lv)) in rhs_args for lv in typing.get_args(lhs)) # XXX: This case is kind of a hack, to support NoLiterals. elif rhs is typing.Literal: