Skip to content

Commit 17aee4f

Browse files
make proper subtyping require last_known_value subtyping
1 parent 35ec958 commit 17aee4f

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

mypy/subtypes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,13 @@ def visit_instance(self, left: Instance) -> bool:
549549
assert isinstance(erased, Instance)
550550
t = erased
551551
nominal = True
552+
if self.proper_subtype and right.last_known_value is not None:
553+
if left.last_known_value is None:
554+
# E.g. str is not a proper subtype of Literal["x"]?
555+
nominal = False
556+
else:
557+
# E.g. Literal[A]? <: Literal[B]? requires A <: B
558+
nominal &= self._is_subtype(left.last_known_value, right.last_known_value)
552559
if right.type.has_type_var_tuple_type:
553560
# For variadic instances we simply find the correct type argument mappings,
554561
# all the heavy lifting is done by the tuple subtyping.

mypy/test/testsubtypes.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ def test_literal(self) -> None:
304304
self.assert_subtype(str1_inst, str1)
305305
self.assert_subtype(str1_inst, str1_inst)
306306

307-
# second operand is a different literal
307+
# other operand is a different literal
308308
# "x" ≲ "y" -> NO
309309
# "x" ≲ "y"? -> YES
310310
# "x"? ≲ "y" -> NO
@@ -315,17 +315,17 @@ def test_literal(self) -> None:
315315
self.assert_subtype(str1_inst, str2_inst)
316316

317317
# check proper subtyping
318-
# second operand is the fallback type
318+
# other operand is the fallback type
319319
# "x" <: str -> YES
320320
# str <: "x" -> NO
321321
# "x"? <: str -> YES
322-
# str <: "x"? -> YES
322+
# str <: "x"? -> NO
323323
self.assert_proper_subtype(str1, str_type)
324324
self.assert_not_proper_subtype(str_type, str1)
325325
self.assert_proper_subtype(str1_inst, str_type)
326-
self.assert_proper_subtype(str_type, str1_inst)
326+
self.assert_not_proper_subtype(str_type, str1_inst)
327327

328-
# second operand is the same literal
328+
# other operand is the same literal
329329
# "x" <: "x" -> YES
330330
# "x" <: "x"? -> YES
331331
# "x"? <: "x" -> NO
@@ -335,15 +335,15 @@ def test_literal(self) -> None:
335335
self.assert_not_proper_subtype(str1_inst, str1)
336336
self.assert_proper_subtype(str1_inst, str1_inst)
337337

338-
# second operand is a different literal
339-
# "x" "y" -> NO
340-
# "x" "y"? -> NO
341-
# "x"? "y" -> NO
342-
# "x"? "y"? -> YES
338+
# other operand is a different literal
339+
# "x" <: "y" -> NO
340+
# "x" <: "y"? -> NO
341+
# "x"? <: "y" -> NO
342+
# "x"? <: "y"? -> NO
343343
self.assert_not_proper_subtype(str1, str2)
344344
self.assert_not_proper_subtype(str1, str2_inst)
345345
self.assert_not_proper_subtype(str1_inst, str2)
346-
self.assert_proper_subtype(str1_inst, str2_inst)
346+
self.assert_not_proper_subtype(str1_inst, str2_inst)
347347

348348
# IDEA: Maybe add these test cases (they are tested pretty well in type
349349
# checker tests already):

0 commit comments

Comments
 (0)