diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index c386555a8df5..55c2e63c9c25 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -1,4 +1,5 @@ [case testForcedAssignment] +# flags: --warn-unreachable x = 1 # type: object y = 1 def f(): x, y # Prevent independent redefinition @@ -8,6 +9,7 @@ y = x [builtins fixtures/tuple.pyi] [case testJoinAny] +# flags: --warn-unreachable from typing import List, Any x: List[Any] @@ -24,6 +26,7 @@ x * 2 [builtins fixtures/list.pyi] [case testGeneratorExpressionTypes] +# flags: --warn-unreachable class A: y = 1 x = [A()] y = [x] @@ -33,6 +36,7 @@ z = [a.y for b in y for a in b] [builtins fixtures/list.pyi] [case testIsinstanceNestedTuple] +# flags: --warn-unreachable from typing import Union, List, Tuple, Dict def f(x: Union[int, str, List]) -> None: @@ -50,6 +54,7 @@ def f(x: Union[int, str, List]) -> None: [builtins fixtures/isinstancelist.pyi] [case testClassAttributeInitialization] +# flags: --warn-unreachable class A: x: int def __init__(self) -> None: @@ -58,6 +63,7 @@ class A: w = self.y [case testAssignmentSubtypes] +# flags: --warn-unreachable from typing import Union def foo(x: Union[str, int]): @@ -76,6 +82,7 @@ y = [x] [builtins fixtures/isinstancelist.pyi] [case testFunctionDefaultArgs] +# flags: --warn-unreachable class A: pass class B(A): y = 1 @@ -86,6 +93,7 @@ def foo(x: A = B()): [builtins fixtures/isinstance.pyi] [case testIsinstanceFancyConditionals] +# flags: --warn-unreachable class A: pass class B(A): @@ -102,6 +110,7 @@ while isinstance(x, B): [builtins fixtures/isinstance.pyi] [case testSubtypingWithAny] +# flags: --warn-unreachable class A: y = 1 @@ -119,10 +128,12 @@ if int(): reveal_type(x) # N: Revealed type is "__main__.A" [case testSingleMultiAssignment] +# flags: --warn-unreachable x = 'a' (x,) = ('a',) [case testUnionMultiAssignment] +# flags: --warn-unreachable from typing import Union x: Union[int, str] if int(): @@ -135,6 +146,7 @@ if int(): [builtins fixtures/isinstancelist.pyi] [case testUnionIfZigzag] +# flags: --warn-unreachable from typing import Union def f(x: Union[int, str]) -> None: @@ -148,6 +160,7 @@ def f(x: Union[int, str]) -> None: [builtins fixtures/isinstancelist.pyi] [case testTwoLoopsUnion] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -167,6 +180,7 @@ def bar() -> None: [builtins fixtures/isinstancelist.pyi] [case testComplicatedBlocks] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -201,6 +215,7 @@ def bar() -> None: [builtins fixtures/isinstancelist.pyi] [case testUnionTryExcept] +# flags: --warn-unreachable class A: y = A() @@ -221,6 +236,7 @@ except: x.z # E: "A" has no attribute "z" [case testUnionTryExcept2] +# flags: --warn-unreachable class A: y = A() @@ -242,6 +258,7 @@ else: x.z [case testUnionTryExcept3] +# flags: --warn-unreachable class A: y = A() @@ -253,7 +270,7 @@ def f(): x # Prevent redefinition of x x = B() try: raise BaseException() - x = A() + x = A() # E: Statement is unreachable except: pass x.z @@ -285,6 +302,7 @@ x.z # E: "A" has no attribute "z" [builtins fixtures/exception.pyi] [case testUnionTryExcept4] +# flags: --warn-unreachable class A: pass class B(A): @@ -303,6 +321,7 @@ while bool(): [builtins fixtures/exception.pyi] [case testUnionTryFinally] +# flags: --warn-unreachable class A: pass class B(A): @@ -320,6 +339,7 @@ finally: x.b [case testUnionTryFinally2] +# flags: --warn-unreachable class A: pass class B(A): @@ -338,6 +358,7 @@ finally: x.b # E: "A" has no attribute "b" [case testUnionTryFinally3] +# flags: --warn-unreachable class A: pass class B(A): @@ -356,6 +377,7 @@ finally: x.b [case testUnionTryFinally4] +# flags: --warn-unreachable class A: pass class B(A): @@ -378,6 +400,7 @@ while 2: [builtins fixtures/isinstancelist.pyi] [case testUnionTryFinally5] +# flags: --warn-unreachable class A: pass class B(A): @@ -391,10 +414,11 @@ while 2: finally: x.b # E: "A" has no attribute "b" break - x.b - x.b + x.b # E: Statement is unreachable + x.b # E: Statement is unreachable [case testUnionTryFinally6] +# flags: --warn-unreachable class A: pass class B(A): @@ -412,6 +436,7 @@ def f() -> int: return x.b # E: "A" has no attribute "b" [case testUnionListIsinstance] +# flags: --warn-unreachable from typing import Union, List def f(x: Union[List[int], List[str], int]) -> None: @@ -436,6 +461,7 @@ def f(x: Union[List[int], List[str], int]) -> None: [builtins fixtures/isinstancelist.pyi] [case testUnionListIsinstance2] +# flags: --warn-unreachable from typing import Union, List class A: @@ -455,6 +481,7 @@ def f(x: Union[A, B, C]) -> None: [builtins fixtures/isinstancelist.pyi] [case testUnionStrictDefnBasic] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -473,6 +500,7 @@ if isinstance(x, str): [builtins fixtures/isinstancelist.pyi] [case testSubtypeRedefinitionBasic] +# flags: --warn-unreachable from typing import Union class A: pass @@ -487,6 +515,7 @@ x.y # OK: x is known to be a B [builtins fixtures/isinstancelist.pyi] [case testIsInstanceBasic] +# flags: --warn-unreachable from typing import Union x: Union[int, str] if isinstance(x, str): @@ -498,6 +527,7 @@ else: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceIndexing] +# flags: --warn-unreachable from typing import Union x: Union[int, str] j = [x] @@ -510,6 +540,7 @@ else: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceSubClassMember] +# flags: --warn-unreachable from typing import Union class Animal: pass @@ -541,6 +572,7 @@ while bool(): [builtins fixtures/isinstancelist.pyi] [case testIsInstanceSubClassReset] +# flags: --warn-unreachable class A: pass @@ -559,6 +591,7 @@ if isinstance(x.a, B): [builtins fixtures/isinstance.pyi] [case testIsinstanceTuple] +# flags: --warn-unreachable from typing import Union class A: pass @@ -582,6 +615,7 @@ if isinstance(v, (B, C)): [builtins fixtures/isinstance.pyi] [case testIsinstanceNeverWidens] +# flags: --warn-unreachable from typing import Union class A: pass @@ -598,6 +632,7 @@ reveal_type(b) # N: Revealed type is "__main__.A | __main__.B" [builtins fixtures/isinstance.pyi] [case testMemberAssignmentChanges] +# flags: --warn-unreachable from typing import Union class Dog: @@ -614,6 +649,7 @@ pet.paws + 1 [builtins fixtures/isinstancelist.pyi] [case testIsInstanceSubClassMemberHard] +# flags: --warn-unreachable from typing import Union class Animal: @@ -648,6 +684,7 @@ if isinstance(h.pet, Dog): [builtins fixtures/isinstancelist.pyi] [case testIsInstanceReturn] +# flags: --warn-unreachable from typing import Union def foo() -> None: @@ -668,6 +705,7 @@ foo() [builtins fixtures/isinstancelist.pyi] [case testIsInstanceBadBreak] +# flags: --warn-unreachable from typing import Union def foo() -> None: @@ -684,6 +722,7 @@ foo() [builtins fixtures/isinstancelist.pyi] [case testIsInstanceThreeUnion] +# flags: --warn-unreachable from typing import Union, List x: Union[int, str, List[int]] @@ -705,6 +744,7 @@ x + [1] # E: Unsupported operand types for + ("int" and "list[int] [builtins fixtures/isinstancelist.pyi] [case testIsInstanceThreeUnion2] +# flags: --warn-unreachable from typing import Union, List x: Union[int, str, List[int]] while bool(): @@ -722,6 +762,7 @@ x + [1] # E: Unsupported operand types for + ("int" and "list[int] [builtins fixtures/isinstancelist.pyi] [case testIsInstanceThreeUnion3] +# flags: --warn-unreachable from typing import Union, List while bool(): @@ -731,17 +772,20 @@ while bool(): if isinstance(x, int): x + 1 break - elif isinstance(x, str): + elif isinstance(x, str): # E: Statement is unreachable x + 'a' break - x + [1] # These lines aren't reached because x was an int + x + [1] # These lines aren't reached because x was an int # E: Statement is unreachable x + 'a' x + [1] # E: Unsupported operand types for + ("int" and "list[int]") \ # E: Unsupported operand types for + ("str" and "list[int]") \ # N: Left operand is of type "int | str | list[int]" + + [builtins fixtures/isinstancelist.pyi] [case testRemovingTypeRepeatedly] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -773,6 +817,7 @@ x + 'a' # E: Unsupported operand types for + ("int" and "str" [builtins fixtures/isinstancelist.pyi] [case testModifyRepeatedly] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -800,6 +845,7 @@ x + 'a' # E: Unsupported operand types for + ("int" and "str") \ [builtins fixtures/isinstancelist.pyi] [case testModifyLoop] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -820,6 +866,7 @@ while bool(): [builtins fixtures/isinstancelist.pyi] [case testModifyLoop2] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -841,6 +888,7 @@ x + 1 # E: Unsupported operand types for + ("str" and "int") \ [builtins fixtures/isinstancelist.pyi] [case testModifyLoop3] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -869,6 +917,7 @@ x + 1 # E: Unsupported operand types for + ("str" and "int") \ [builtins fixtures/isinstancelist.pyi] [case testModifyLoopWhile4] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -901,6 +950,7 @@ x + 'a' [builtins fixtures/isinstancelist.pyi] [case testModifyLoopFor4] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -933,6 +983,7 @@ x + 'a' [builtins fixtures/isinstancelist.pyi] [case testModifyNestedLoop] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -965,6 +1016,7 @@ x + 1 # E: Unsupported operand types for + ("str" and "int") \ [builtins fixtures/isinstancelist.pyi] [case testModifyLoopLong] +# flags: --warn-unreachable from typing import Union class A: a = 1 @@ -1012,6 +1064,7 @@ def bar() -> None: [builtins fixtures/isinstancelist.pyi] [case testWhileExitCondition1] +# flags: --warn-unreachable from typing import Union x = 1 # type: Union[int, str] while isinstance(x, int): @@ -1024,6 +1077,7 @@ reveal_type(x) # N: Revealed type is "builtins.str" [builtins fixtures/isinstance.pyi] [case testWhileExitCondition2] +# flags: --warn-unreachable from typing import Union x = 1 # type: Union[int, str] while isinstance(x, int): @@ -1036,6 +1090,7 @@ reveal_type(x) # N: Revealed type is "builtins.int | builtins.str" [builtins fixtures/isinstance.pyi] [case testWhileLinkedList] +# flags: --warn-unreachable from typing import Union LinkedList = Union['Cons', 'Nil'] class Nil: pass @@ -1048,10 +1103,12 @@ def last(x: LinkedList) -> Nil: [builtins fixtures/isinstance.pyi] [case testReturnAndFlow] +# flags: --warn-unreachable def foo() -> int: return 1 and 2 - return 'a' + return 'a' # E: Statement is unreachable [case testCastIsinstance] +# flags: --warn-unreachable from typing import Union def foo() -> Union[int, str]: pass @@ -1066,15 +1123,17 @@ x + 'a' # E: Unsupported operand types for + ("int" and "str") [builtins fixtures/isinstancelist.pyi] [case testUnreachableCode] +# flags: --warn-unreachable x = 1 # type: int while bool(): x = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int") break - x = 'a' # Note: no error because unreachable code + x = 'a' # Note: no error because unreachable code # E: Statement is unreachable [builtins fixtures/isinstancelist.pyi] [case testUnreachableCode2] +# flags: --warn-unreachable x = 1 while bool(): try: @@ -1083,50 +1142,56 @@ while bool(): continue else: continue - x + 'a' + x + 'a' # E: Statement is unreachable [builtins fixtures/isinstance.pyi] [case testUnreachableWhileTrue] +# flags: --warn-unreachable def f(x: int) -> None: while True: if x: return - 1() + 1() # E: Statement is unreachable [builtins fixtures/bool.pyi] [case testUnreachableAssertFalse] +# flags: --warn-unreachable def f() -> None: assert False - 1() + 1() # E: Statement is unreachable [builtins fixtures/bool.pyi] [case testUnreachableAssertFalse2] +# flags: --warn-unreachable def f() -> None: # The old parser doesn't understand the syntax below assert False, "hi" - 1() + 1() # E: Statement is unreachable [builtins fixtures/bool.pyi] [case testUnreachableReturnOrAssertFalse] +# flags: --warn-unreachable def f(x: int) -> int: if x: return x else: assert False - 1() + 1() # E: Statement is unreachable [builtins fixtures/bool.pyi] [case testUnreachableTryExcept] +# flags: --warn-unreachable def f() -> None: try: f() return except BaseException: return - 1() + 1() # E: Statement is unreachable [builtins fixtures/exception.pyi] [case testUnreachableTryExceptElse] +# flags: --warn-unreachable def f() -> None: try: f() @@ -1134,41 +1199,46 @@ def f() -> None: return else: return - 1() + 1() # E: Statement is unreachable [builtins fixtures/exception.pyi] [case testUnreachableTryReturnFinally1] +# flags: --warn-unreachable def f() -> None: try: return finally: pass - 1() + 1() # E: Statement is unreachable [case testUnreachableTryReturnFinally2] +# flags: --warn-unreachable def f() -> None: try: pass finally: return - 1() + 1() # E: Statement is unreachable [case testUnreachableTryReturnExceptRaise] +# flags: --warn-unreachable def f() -> None: try: return except: raise - 1() + 1() # E: Statement is unreachable [case testUnreachableReturnLambda] +# flags: --warn-unreachable from typing import Callable def g(t: Callable[[int], int]) -> int: pass def f() -> int: return g(lambda x: x) - 1() + 1() # E: Statement is unreachable [case testIsinstanceAnd] +# flags: --warn-unreachable class A: pass class B(A): @@ -1181,6 +1251,7 @@ if isinstance(x, B) and 1: [builtins fixtures/isinstancelist.pyi] [case testIsinstanceShortcircuit] +# flags: --warn-unreachable class A: pass @@ -1200,6 +1271,7 @@ if not isinstance(x, B) and x.flag: # E: "A" has no attribute "flag" [builtins fixtures/isinstancelist.pyi] [case testIsinstanceExpression] +# flags: --warn-unreachable class A: pass @@ -1214,6 +1286,7 @@ x.flag if isinstance(x, B) else 0 [builtins fixtures/isinstancelist.pyi] [case testIsinstanceMultiAnd] +# flags: --warn-unreachable class A: pass class B(A): @@ -1236,6 +1309,7 @@ else: [builtins fixtures/isinstancelist.pyi] [case testIsinstanceMultiAndSpecialCase] +# flags: --warn-unreachable class A: # Ensure A.__add__ and int.__add__ are different to # force 'isinstance(y, int)' checks below to never succeed. @@ -1250,15 +1324,18 @@ class C(A): x = B() # type: A y = C() # type: A -if isinstance(x, B) and isinstance(y, int): - 1() # type checking skipped -if isinstance(y, int) and isinstance(x, B): - 1() # type checking skipped -if isinstance(y, int) and y > 42: - 1() # type checking skipped +if isinstance(x, B) and isinstance(y, int): # E: Subclass of "A" and "int" cannot exist: would have incompatible method signatures + 1() # E: Statement is unreachable +if isinstance(y, int) and isinstance(x, B): # E: Subclass of "A" and "int" cannot exist: would have incompatible method signatures \ + # E: Right operand of "and" is never evaluated + 1() # E: Statement is unreachable +if isinstance(y, int) and y > 42: # E: Subclass of "A" and "int" cannot exist: would have incompatible method signatures \ + # E: Right operand of "and" is never evaluated + 1() # E: Statement is unreachable [builtins fixtures/isinstancelist.pyi] [case testReturnWithCallExprAndIsinstance] +# flags: --warn-unreachable from typing import Union def f(x: Union[int, str]) -> None: @@ -1270,6 +1347,7 @@ def foo(): pass [builtins fixtures/isinstancelist.pyi] [case testIsinstanceOr1] +# flags: --warn-unreachable from typing import Optional def f(a: bool, x: object) -> Optional[int]: @@ -1280,6 +1358,7 @@ def f(a: bool, x: object) -> Optional[int]: [builtins fixtures/isinstance.pyi] [case testIsinstanceOr2] +# flags: --warn-unreachable from typing import Optional def g(a: bool, x: object) -> Optional[int]: @@ -1290,6 +1369,7 @@ def g(a: bool, x: object) -> Optional[int]: [builtins fixtures/isinstance.pyi] [case testIsinstanceOr3] +# flags: --warn-unreachable from typing import Optional def h(a: bool, x: object) -> Optional[int]: @@ -1299,6 +1379,7 @@ def h(a: bool, x: object) -> Optional[int]: [builtins fixtures/isinstance.pyi] [case testIsinstanceWithOverlappingUnionType] +# flags: --warn-unreachable from typing import Union def f(x: Union[float, int]) -> None: @@ -1309,6 +1390,7 @@ def f(x: Union[float, int]) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceWithOverlappingUnionType2] +# flags: --warn-unreachable from typing import Union class A: pass @@ -1322,6 +1404,7 @@ def f(x: Union[A, B]) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceWithOverlappingPromotionTypes] +# flags: --warn-unreachable from typing import Union class FloatLike: pass @@ -1341,6 +1424,7 @@ def f2(x: Union[FloatLike, IntLike]) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceOfSuperclass] +# flags: --warn-unreachable class A: pass class B(A): pass @@ -1348,12 +1432,13 @@ x = B() if isinstance(x, A): reveal_type(x) # N: Revealed type is "__main__.B" if not isinstance(x, A): - reveal_type(x) # unreachable + reveal_type(x) # E: Statement is unreachable x = A() reveal_type(x) # N: Revealed type is "__main__.B" [builtins fixtures/isinstance.pyi] [case testIsinstanceOfNonoverlapping] +# flags: --warn-unreachable class A: pass class B: pass @@ -1366,6 +1451,7 @@ reveal_type(x) # N: Revealed type is "__main__.B" [builtins fixtures/isinstance.pyi] [case testAssertIsinstance] +# flags: --warn-unreachable def f(x: object): assert isinstance(x, int) y = 0 # type: int @@ -1373,6 +1459,7 @@ def f(x: object): [builtins fixtures/isinstance.pyi] [case testUnionAssertIsinstance] +# flags: --warn-unreachable from typing import Union def f(x: Union[str, int]): @@ -1382,6 +1469,7 @@ def f(x: Union[str, int]): [builtins fixtures/isinstance.pyi] [case testAnyAssertIsinstance] +# flags: --warn-unreachable from typing import Any def f(x: Any): @@ -1390,6 +1478,7 @@ def f(x: Any): [builtins fixtures/isinstance.pyi] [case testIsinstanceOfGenericClassRetainsParameters] +# flags: --warn-unreachable from typing import List, Union def f(x: Union[List[int], str]) -> None: @@ -1401,6 +1490,7 @@ def f(x: Union[List[int], str]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsinstanceOrIsinstance] +# flags: --warn-unreachable class A: pass class B(A): @@ -1418,16 +1508,16 @@ else: f = 0 reveal_type(x1) # N: Revealed type is "__main__.A" x2 = A() -if isinstance(x2, A) or isinstance(x2, C): +if isinstance(x2, A) or isinstance(x2, C): # E: Right operand of "or" is never evaluated reveal_type(x2) # N: Revealed type is "__main__.A" f = x2.flag # E: "A" has no attribute "flag" else: - # unreachable - 1() + 1() # E: Statement is unreachable reveal_type(x2) # N: Revealed type is "__main__.A" [builtins fixtures/isinstance.pyi] [case testComprehensionIsInstance] +# flags: --warn-unreachable from typing import List, Union a = [] # type: List[Union[int, str]] l = [x for x in a if isinstance(x, int)] @@ -1439,6 +1529,7 @@ reveal_type(d) # N: Revealed type is "builtins.dict[builtins.int, builtins.int]" [builtins fixtures/isinstancelist.pyi] [case testIsinstanceInWrongOrderInBooleanOp] +# flags: --warn-unreachable class A: m = 1 @@ -1448,6 +1539,7 @@ def f(x: object) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceAndOr] +# flags: --warn-unreachable class A: a: 'A' @@ -1457,6 +1549,7 @@ def f(x: object) -> None: [builtins fixtures/isinstance.pyi] [case testIsInstanceWithUnknownType] +# flags: --warn-unreachable from typing import Union def f(x: Union[int, str], typ: type) -> None: @@ -1470,6 +1563,7 @@ def f(x: Union[int, str], typ: type) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceWithBoundedType] +# flags: --warn-unreachable from typing import Union, Type class A: pass @@ -1494,6 +1588,7 @@ def f(x: Union[int, str]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceWithTypeObject] +# flags: --warn-unreachable from typing import Union, Type class A: pass @@ -1509,11 +1604,12 @@ def f(x: Union[int, A], a: Type[A]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclassUnreachable] +# flags: --warn-unreachable from typing import Type, Sequence, Union x: Type[str] -if issubclass(x, int): - reveal_type(x) # unreachable block +if issubclass(x, int): # E: Subclass of "str" and "int" cannot exist: would have incompatible method signatures + reveal_type(x) # E: Statement is unreachable class X: pass class Y(X): pass @@ -1523,10 +1619,11 @@ a: Union[Type[Y], Type[Z]] if issubclass(a, X): reveal_type(a) # N: Revealed type is "type[__main__.Y] | type[__main__.Z]" else: - reveal_type(a) # unreachable block + reveal_type(a) # E: Statement is unreachable [builtins fixtures/isinstancelist.pyi] [case testIssubclasDestructuringUnions1] +# flags: --warn-unreachable from typing import Union, List, Tuple, Dict, Type def f(x: Union[Type[int], Type[str], Type[List]]) -> None: if issubclass(x, (str, (int,))): @@ -1548,6 +1645,7 @@ def f(x: Union[Type[int], Type[str], Type[List]]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclasDestructuringUnions2] +# flags: --warn-unreachable from typing import Union, List, Tuple, Dict, Type def f(x: Type[Union[int, str, List]]) -> None: @@ -1570,6 +1668,7 @@ def f(x: Type[Union[int, str, List]]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclasDestructuringUnions3] +# flags: --warn-unreachable from typing import Union, List, Tuple, Dict, Type def f(x: Type[Union[int, str, List]]) -> None: @@ -1594,6 +1693,7 @@ def f(x: Type[Union[int, str, List]]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclass] +# flags: --warn-unreachable from typing import Type, ClassVar class Goblin: @@ -1621,6 +1721,7 @@ def test_issubclass(cls: Type[Goblin]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclassDeepHierarchy] +# flags: --warn-unreachable from typing import Type, ClassVar class Mob: pass @@ -1674,6 +1775,7 @@ def test_issubclass(cls: Type[Mob]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclassTuple] +# flags: --warn-unreachable from typing import Type, ClassVar class Mob: pass @@ -1730,6 +1832,7 @@ def test_issubclass(cls: Type[Mob]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIssubclassBuiltins] +# flags: --warn-unreachable from typing import List, Type class MyList(List): pass @@ -1764,6 +1867,7 @@ def directed_meet(cls0: ClassT, cls1: ClassT) -> ClassT | None: [builtins fixtures/isinstancelist.pyi] [case testIsinstanceTypeArgs] +# flags: --warn-unreachable from typing import Iterable, TypeVar x = 1 isinstance(x, Iterable) @@ -1774,12 +1878,14 @@ isinstance(x, (int, (str, Iterable[int]))) # E: Parameterized generics cannot b [typing fixtures/typing-full.pyi] [case testIsinstanceAnyAlias] +# flags: --warn-unreachable from typing import Any A = Any isinstance(object(), A) # E: Cannot use isinstance() with Any type [builtins fixtures/isinstance.pyi] [case testIsinstanceTypeArgsAliases] +# flags: --warn-unreachable from typing import Iterable, TypeVar x = 1 T = TypeVar('T') @@ -1794,6 +1900,7 @@ isinstance(x, It2) # E: Parameterized generics cannot be used with class or ins [typing fixtures/typing-full.pyi] [case testIssubclassTypeArgs] +# flags: --warn-unreachable from typing import Iterable, TypeVar x = int issubclass(x, Iterable) @@ -1803,7 +1910,7 @@ issubclass(x, (int, Iterable[int])) # E: Parameterized generics cannot be used [typing fixtures/typing-full.pyi] [case testIssubclassWithMetaclasses] -# flags: --no-strict-optional +# flags: --no-strict-optional --warn-unreachable class FooMetaclass(type): ... class Foo(metaclass=FooMetaclass): ... class Bar: ... @@ -1817,6 +1924,7 @@ if issubclass(fm, Bar): [builtins fixtures/isinstance.pyi] [case testIssubclassWithMetaclassesStrictOptional] +# flags: --warn-unreachable class FooMetaclass(type): ... class BarMetaclass(type): ... class Foo(metaclass=FooMetaclass): ... @@ -1834,6 +1942,7 @@ if issubclass(fm, Baz): [builtins fixtures/isinstance.pyi] [case testIsinstanceAndNarrowTypeVariable] +# flags: --warn-unreachable from typing import TypeVar class A: pass @@ -1854,6 +1963,7 @@ def f(x: T) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceAndNegativeNarrowTypeVariableWithUnionBound1] +# flags: --warn-unreachable from typing import Union, TypeVar class A: @@ -1880,6 +1990,7 @@ def f(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testIsinstanceAndNegativeNarrowTypeVariableWithUnionBound2] +# flags: --warn-unreachable from typing import Union, TypeVar class A: @@ -1898,16 +2009,18 @@ def f(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testIsinstanceAndTypeType] +# flags: --warn-unreachable from typing import Type def f(x: Type[int]) -> None: if isinstance(x, type): reveal_type(x) # N: Revealed type is "type[builtins.int]" else: - reveal_type(x) # Unreachable + reveal_type(x) # E: Statement is unreachable reveal_type(x) # N: Revealed type is "type[builtins.int]" [builtins fixtures/isinstance.pyi] [case testIsinstanceVariableSubstitution] +# flags: --warn-unreachable T = (int, str) U = (list, T) x: object = None @@ -1923,6 +2036,7 @@ if isinstance(x, (set, (list, T))): [builtins fixtures/isinstancelist.pyi] [case testIsInstanceTooFewArgs] +# flags: --warn-unreachable isinstance() # E: Missing positional arguments "x", "t" in call to "isinstance" x: object if isinstance(): # E: Missing positional arguments "x", "t" in call to "isinstance" @@ -1934,6 +2048,7 @@ if isinstance(x): # E: Missing positional argument "t" in call to "isinstance" [builtins fixtures/isinstancelist.pyi] [case testIsSubclassTooFewArgs] +# flags: --warn-unreachable from typing import Type issubclass() # E: Missing positional arguments "x", "t" in call to "issubclass" @@ -1946,6 +2061,7 @@ if issubclass(y): # E: Missing positional argument "t" in call to "issubclass" [builtins fixtures/isinstancelist.pyi] [case testIsInstanceTooManyArgs] +# flags: --warn-unreachable isinstance(1, 1, 1) # E: Too many arguments for "isinstance" \ # E: Argument 2 to "isinstance" has incompatible type "int"; expected "type | tuple[Any, ...]" x: object @@ -1956,6 +2072,7 @@ if isinstance(x, str, 1): # E: Too many arguments for "isinstance" [builtins fixtures/isinstancelist.pyi] [case testIsinstanceNarrowAnyExplicit] +# flags: --warn-unreachable from typing import Any def narrow_any_to_str_then_reassign_to_int() -> None: @@ -1968,6 +2085,7 @@ def narrow_any_to_str_then_reassign_to_int() -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceNarrowAnyImplicit] +# flags: --warn-unreachable def foo(): ... def narrow_any_to_str_then_reassign_to_int() -> None: @@ -1980,6 +2098,7 @@ def narrow_any_to_str_then_reassign_to_int() -> None: [builtins fixtures/isinstance.pyi] [case testNarrowTypeAfterInList] +# flags: --warn-unreachable from typing import List, Optional x: List[int] @@ -1997,6 +2116,7 @@ else: [out] [case testNarrowTypeAfterInListOfOptional] +# flags: --warn-unreachable from typing import List, Optional x: List[Optional[int]] @@ -2010,6 +2130,7 @@ else: [out] [case testNarrowTypeAfterInListNonOverlapping] +# flags: --warn-unreachable from typing import List, Optional x: List[str] @@ -2037,6 +2158,7 @@ if x in nested_any: [builtins fixtures/list.pyi] [case testNarrowTypeAfterInTuple] +# flags: --warn-unreachable from typing import Optional class A: pass class B(A): pass @@ -2051,6 +2173,7 @@ else: [out] [case testNarrowTypeAfterInNamedTuple] +# flags: --warn-unreachable from typing import NamedTuple, Optional class NT(NamedTuple): x: int @@ -2066,6 +2189,7 @@ else: [out] [case testNarrowTypeAfterInDict] +# flags: --warn-unreachable from typing import Dict, Optional x: Dict[str, int] y: Optional[str] @@ -2082,6 +2206,7 @@ else: [out] [case testNarrowTypeAfterInNoAnyOrObject] +# flags: --warn-unreachable from typing import Any, List, Optional x: List[Any] z: List[object] @@ -2101,6 +2226,7 @@ else: [out] [case testNarrowTypeAfterInUserDefined] +# flags: --warn-unreachable from typing import Container, Optional class C(Container[int]): @@ -2122,6 +2248,7 @@ else: [out] [case testNarrowTypeAfterInSet] +# flags: --warn-unreachable from typing import Optional, Set s: Set[str] @@ -2138,6 +2265,7 @@ else: [out] [case testNarrowTypeAfterInTypedDict] +# flags: --warn-unreachable from typing import Optional, TypedDict class TD(TypedDict): a: int @@ -2154,6 +2282,7 @@ def f() -> None: [out] [case testIsinstanceWidensWithAnyArg] +# flags: --warn-unreachable from typing import Any class A: ... B: Any @@ -2165,6 +2294,7 @@ reveal_type(x) # N: Revealed type is "Any" [builtins fixtures/isinstance.pyi] [case testIsinstanceWidensUnionWithAnyArg] +# flags: --warn-unreachable from typing import Any, Union class A: ... B: Any @@ -2175,6 +2305,7 @@ reveal_type(x) # N: Revealed type is "Any" [builtins fixtures/isinstance.pyi] [case testIsinstanceIgnoredImport] +# flags: --warn-unreachable from typing import Union from foo import A # type: ignore def f(x: Union[A, str]) -> None: @@ -2184,6 +2315,7 @@ def f(x: Union[A, str]) -> None: [builtins fixtures/isinstance.pyi] [case testIsinstanceIgnoredImportDualAny] +# flags: --warn-unreachable from typing import Any from foo import Bad, OtherBad # type: ignore x: Any @@ -2212,6 +2344,7 @@ else: [builtins fixtures/isinstance.pyi] [case testIsInstanceInitialNoneCheckSkipsImpossibleCasesNoStrictOptional] +# flags: --warn-unreachable from typing import Optional, Union class A: pass @@ -2234,7 +2367,7 @@ def foo2(x: Optional[str]) -> None: [builtins fixtures/isinstance.pyi] [case testIsInstanceInitialNoneCheckSkipsImpossibleCasesInNoStrictOptional] -# flags: --no-strict-optional +# flags: --no-strict-optional --warn-unreachable from typing import Optional, Union class A: pass @@ -2258,6 +2391,7 @@ def foo2(x: Optional[str]) -> None: [builtins fixtures/isinstance.pyi] [case testNoneCheckDoesNotMakeTypeVarOptional] +# flags: --warn-unreachable from typing import TypeVar T = TypeVar('T') @@ -2278,7 +2412,7 @@ def foo_while(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testNoneCheckDoesNotNarrowWhenUsingTypeVarsNoStrictOptional] -# flags: --no-strict-optional +# flags: --no-strict-optional --warn-unreachable from typing import TypeVar T = TypeVar('T') @@ -2292,7 +2426,7 @@ def foo(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testNoneAndGenericTypesOverlapNoStrictOptional] -# flags: --no-strict-optional +# flags: --no-strict-optional --warn-unreachable from typing import Union, Optional, List # Note: this test is indirectly making sure meet.is_overlapping_types @@ -2310,6 +2444,7 @@ def bar(x: Union[List[str], List[int], None]) -> None: [builtins fixtures/isinstancelist.pyi] [case testNoneAndGenericTypesOverlapStrictOptional] +# flags: --warn-unreachable from typing import Union, Optional, List # This test is the same as the one above, except for strict-optional. @@ -2328,6 +2463,7 @@ def bar(x: Union[List[str], List[int], None]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceWithStarExpression] +# flags: --warn-unreachable from typing import Union, List, Tuple def f(var: Union[List[str], Tuple[str, str], str]) -> None: @@ -2337,6 +2473,7 @@ def f(var: Union[List[str], Tuple[str, str], str]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceWithStarExpressionAndVariable] +# flags: --warn-unreachable from typing import Union def f(var: Union[int, str]) -> None: @@ -2348,12 +2485,14 @@ def f(var: Union[int, str]) -> None: [builtins fixtures/isinstancelist.pyi] [case testIsInstanceWithWrongStarExpression] +# flags: --warn-unreachable var = 'some string' if isinstance(var, *(str, int)): # E: Too many arguments for "isinstance" pass [builtins fixtures/isinstancelist.pyi] [case testIsInstanceAdHocIntersectionBasic] +# flags: --warn-unreachable class A: def f1(self) -> int: ... class B: @@ -2715,6 +2854,7 @@ else: [builtins fixtures/isinstance.pyi] [case testHasAttrExistingAttribute] +# flags: --warn-unreachable class C: x: int c: C @@ -2726,6 +2866,7 @@ else: [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeInstance] +# flags: --warn-unreachable class B: ... b: B if hasattr(b, "x"): @@ -2735,18 +2876,21 @@ else: [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeFunction] +# flags: --warn-unreachable def foo(x: int) -> None: ... if hasattr(foo, "x"): reveal_type(foo.x) # N: Revealed type is "Any" [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeClassObject] +# flags: --warn-unreachable class C: ... if hasattr(C, "x"): reveal_type(C.x) # N: Revealed type is "Any" [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeTypeType] +# flags: --warn-unreachable from typing import Type class C: ... c: Type[C] @@ -2755,6 +2899,7 @@ if hasattr(c, "x"): [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeTypeVar] +# flags: --warn-unreachable from typing import TypeVar T = TypeVar("T") @@ -2767,6 +2912,7 @@ def foo(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeChained] +# flags: --warn-unreachable class B: ... b: B if hasattr(b, "x"): @@ -2776,6 +2922,7 @@ elif hasattr(b, "y"): [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeNested] +# flags: --warn-unreachable class A: ... class B: ... @@ -2799,6 +2946,7 @@ if hasattr(x, "x") or hasattr(x, "y"): [builtins fixtures/isinstance.pyi] [case testHasAttrPreciseType] +# flags: --warn-unreachable class A: ... x: A @@ -2807,6 +2955,7 @@ if hasattr(x, "a") and isinstance(x.a, int): [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeUnion] +# flags: --warn-unreachable from typing import Union class A: ... @@ -2822,6 +2971,7 @@ else: [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeOuterUnion] +# flags: --warn-unreachable from typing import Union class A: ... @@ -2836,6 +2986,7 @@ if isinstance(xu, B) and hasattr(xu, "x"): [builtins fixtures/isinstance.pyi] [case testHasAttrDoesntInterfereGetAttr] +# flags: --warn-unreachable class C: def __getattr__(self, attr: str) -> str: ... @@ -2845,6 +2996,7 @@ if hasattr(c, "foo"): [builtins fixtures/isinstance.pyi] [case testHasAttrMissingAttributeLiteral] +# flags: --warn-unreachable from typing import Final class B: ... b: B @@ -2856,6 +3008,7 @@ else: [builtins fixtures/isinstance.pyi] [case testHasAttrDeferred] +# flags: --warn-unreachable def foo() -> str: ... class Test: @@ -2870,6 +3023,7 @@ class Test: [builtins fixtures/isinstance.pyi] [case testHasAttrModule] +# flags: --warn-unreachable import mod if hasattr(mod, "y"): @@ -2891,6 +3045,7 @@ x: int [builtins fixtures/module.pyi] [case testHasAttrDoesntInterfereModuleGetAttr] +# flags: --warn-unreachable import mod if hasattr(mod, "y"): @@ -2919,6 +3074,7 @@ def f(x: type | str): [builtins fixtures/module.pyi] [case testTypeIsntLostAfterNarrowing] +# flags: --warn-unreachable from typing import Any var: Any @@ -2934,6 +3090,7 @@ reveal_type(var) # N: Revealed type is "builtins.bool | builtins.str" [builtins fixtures/isinstance.pyi] [case testReuseIntersectionForRepeatedIsinstanceCalls] +# flags: --warn-unreachable class A: ... class B: ... diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index b9bb0c1efa6a..e10f858ff15b 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -1,4 +1,5 @@ [case testNarrowingParentWithStrsBasic] +# flags: --strict-equality --warn-unreachable from dataclasses import dataclass from typing import Literal, NamedTuple, Tuple, TypedDict, Union @@ -82,6 +83,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingParentWithEnumsBasic] +# flags: --strict-equality --warn-unreachable from enum import Enum from dataclasses import dataclass from typing import Literal, NamedTuple, Tuple, TypedDict, Union @@ -171,6 +173,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingParentWithIsInstanceBasic] +# flags: --strict-equality --warn-unreachable from dataclasses import dataclass from typing import NamedTuple, Tuple, TypedDict, Union @@ -236,7 +239,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingParentMultipleKeys] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from enum import Enum from typing import Literal, Union @@ -262,14 +265,14 @@ if x.key is Key.C: else: reveal_type(x) # N: Revealed type is "__main__.Object1 | __main__.Object2" -if x.key is Key.D: +if x.key is Key.D: # E: Non-overlapping identity check (left operand type: "Literal[Key.A, Key.C, Key.B]", right operand type: "Literal[Key.D]") reveal_type(x) # E: Statement is unreachable else: reveal_type(x) # N: Revealed type is "__main__.Object1 | __main__.Object2" [builtins fixtures/tuple.pyi] [case testNarrowingTypedDictParentMultipleKeys] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union class TypedDict1(TypedDict): @@ -288,7 +291,7 @@ if x['key'] == 'C': else: reveal_type(x) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key': Literal['A'] | Literal['C']}) | TypedDict('__main__.TypedDict2', {'key': Literal['B'] | Literal['C']})" -if x['key'] == 'D': +if x['key'] == 'D': # E: Non-overlapping equality check (left operand type: "Literal['A', 'C', 'B']", right operand type: "Literal['D']") reveal_type(x) # E: Statement is unreachable else: reveal_type(x) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key': Literal['A'] | Literal['C']}) | TypedDict('__main__.TypedDict2', {'key': Literal['B'] | Literal['C']})" @@ -296,7 +299,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingPartialTypedDictParentMultipleKeys] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union class TypedDict1(TypedDict, total=False): @@ -315,7 +318,7 @@ if x['key'] == 'C': else: reveal_type(x) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key'?: Literal['A'] | Literal['C']}) | TypedDict('__main__.TypedDict2', {'key'?: Literal['B'] | Literal['C']})" -if x['key'] == 'D': +if x['key'] == 'D': # E: Non-overlapping equality check (left operand type: "Literal['A', 'C', 'B']", right operand type: "Literal['D']") reveal_type(x) # E: Statement is unreachable else: reveal_type(x) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key'?: Literal['A'] | Literal['C']}) | TypedDict('__main__.TypedDict2', {'key'?: Literal['B'] | Literal['C']})" @@ -323,6 +326,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingNestedTypedDicts] +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union class A(TypedDict): @@ -351,6 +355,7 @@ if unknown['inner']['key'] == 'C': [typing fixtures/typing-typeddict.pyi] [case testNarrowingParentWithMultipleParents] +# flags: --strict-equality --warn-unreachable from enum import Enum from typing import Literal, Union @@ -381,6 +386,7 @@ else: [builtins fixtures/isinstance.pyi] [case testNarrowingParentsWithGenerics] +# flags: --strict-equality --warn-unreachable from typing import Union, TypeVar, Generic T = TypeVar('T') @@ -395,6 +401,7 @@ else: [builtins fixtures/isinstance.pyi] [case testNarrowingParentWithParentMixtures] +# flags: --strict-equality --warn-unreachable from enum import Enum from typing import Literal, Union, NamedTuple, TypedDict @@ -444,6 +451,7 @@ else: [typing fixtures/typing-full.pyi] [case testNarrowingParentWithProperties] +# flags: --strict-equality --warn-unreachable from enum import Enum from typing import Literal, Union @@ -471,6 +479,7 @@ else: [builtins fixtures/property.pyi] [case testNarrowingParentWithAny] +# flags: --strict-equality --warn-unreachable from enum import Enum from typing import Literal, Union, Any @@ -496,6 +505,7 @@ else: [builtins fixtures/tuple.pyi] [case testNarrowingParentsHierarchy] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union from enum import Enum @@ -553,6 +563,7 @@ else: [builtins fixtures/tuple.pyi] [case testNarrowingParentsHierarchyGenerics] +# flags: --strict-equality --warn-unreachable from typing import Generic, TypeVar, Union T = TypeVar('T') @@ -573,7 +584,7 @@ else: [builtins fixtures/isinstance.pyi] [case testNarrowingParentsHierarchyTypedDict] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union from enum import Enum @@ -605,7 +616,7 @@ else: reveal_type(x["model"]) # N: Revealed type is "TypedDict('__main__.Model2', {'key': Literal[__main__.Key.B]})" y: Union[Parent1, Parent2] -if y["model"]["key"] is Key.C: +if y["model"]["key"] is Key.C: # E: Non-overlapping identity check (left operand type: "Literal[Key.A, Key.B]", right operand type: "Literal[Key.C]") reveal_type(y) # E: Statement is unreachable reveal_type(y["model"]) else: @@ -615,7 +626,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingParentsHierarchyTypedDictWithStr] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union class Parent1(TypedDict): @@ -641,7 +652,7 @@ else: reveal_type(x["model"]) # N: Revealed type is "TypedDict('__main__.Model2', {'key': Literal['B']})" y: Union[Parent1, Parent2] -if y["model"]["key"] == 'C': +if y["model"]["key"] == 'C': # E: Non-overlapping equality check (left operand type: "Literal['A', 'B']", right operand type: "Literal['C']") reveal_type(y) # E: Statement is unreachable reveal_type(y["model"]) else: @@ -651,6 +662,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingExprPropagation] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union class A: @@ -671,7 +683,7 @@ if not (abo is None or abo.tag != "B"): [builtins fixtures/primitives.pyi] [case testNarrowingEqualityFlipFlop] -# flags: --warn-unreachable --strict-equality +# flags: --strict-equality --warn-unreachable from typing import Final, Literal from enum import Enum @@ -737,6 +749,7 @@ def test3(switch: FlipFlopEnum) -> None: [builtins fixtures/primitives.pyi] [case testNarrowingEqualityRequiresExplicitStrLiteral] +# flags: --strict-equality --warn-unreachable from typing import Final, Literal A_final: Final = "A" @@ -783,6 +796,7 @@ reveal_type(x_union) # N: Revealed type is "Literal['A'] | Literal['B'] | N [builtins fixtures/primitives.pyi] [case testNarrowingEqualityRequiresExplicitEnumLiteral] +# flags: --strict-equality --warn-unreachable from typing import Final, Literal, Union from enum import Enum @@ -824,6 +838,7 @@ def bar(x: Union[SingletonFoo, Foo], y: SingletonFoo) -> None: [builtins fixtures/primitives.pyi] [case testNarrowingEqualityCustomEqualityDisabled] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union class Custom: @@ -845,6 +860,7 @@ def f2(x: Union[Default, Literal[1], Literal[2]]): [builtins fixtures/primitives.pyi] [case testNarrowingEqualityCustomEqualityEnum] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union from enum import Enum @@ -1076,6 +1092,7 @@ else: [builtins fixtures/primitives.pyi] [case testNarrowingLiteralTruthiness] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union str_or_false: Union[Literal[False], str] @@ -1094,6 +1111,7 @@ else: [builtins fixtures/primitives.pyi] [case testNarrowingFalseyToLiteral] +# flags: --strict-equality --warn-unreachable from typing import Union a: str @@ -1111,7 +1129,7 @@ if not d: reveal_type(d) # N: Revealed type is "Literal[''] | Literal[b''] | Literal[0]" [case testNarrowingIsInstanceFinalSubclass] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import final @@ -1148,7 +1166,7 @@ else: [case testNarrowingIsInstanceFinalSubclassWithUnions] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import final, Union @@ -1182,7 +1200,7 @@ else: [case testNarrowingIsSubclassFinalSubclassWithTypeVar] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import final, Type, TypeVar @@ -1209,6 +1227,7 @@ reveal_type(f(B)) # N: Revealed type is "__main__.B" [case testNarrowingLiteralIdentityCheck] +# flags: --strict-equality --warn-unreachable from typing import Literal, Union str_or_false: Union[Literal[False], str] @@ -1249,6 +1268,7 @@ else: [builtins fixtures/primitives.pyi] [case testNarrowingBooleanIdentityCheck] +# flags: --strict-equality --warn-unreachable from typing import Literal, Optional bool_val: bool @@ -1270,6 +1290,7 @@ else: [builtins fixtures/primitives.pyi] [case testNarrowingBooleanTruthiness] +# flags: --strict-equality --warn-unreachable from typing import Literal, Optional bool_val: bool @@ -1290,6 +1311,7 @@ reveal_type(opt_bool_val) # N: Revealed type is "builtins.bool | None" [builtins fixtures/primitives.pyi] [case testNarrowingBooleanBoolOp] +# flags: --strict-equality --warn-unreachable from typing import Literal, Optional bool_a: bool @@ -1317,6 +1339,7 @@ reveal_type(x) # N: Revealed type is "builtins.bool" [builtins fixtures/primitives.pyi] [case testNarrowingTypedDictUsingEnumLiteral] +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union from enum import Enum @@ -1340,6 +1363,7 @@ def f(d: Union[Foo, Bar]) -> None: [typing fixtures/typing-typeddict.pyi] [case testNarrowingUsingMetaclass] +# flags: --strict-equality --warn-unreachable from typing import Type class M(type): @@ -1359,6 +1383,7 @@ def f(t: Type[C]) -> None: reveal_type(t) # N: Revealed type is "type[__main__.C]" [case testNarrowingUsingTypeVar] +# flags: --strict-equality --warn-unreachable from typing import Type, TypeVar class A: pass @@ -1378,6 +1403,7 @@ def f(t: Type[T], a: A, b: B) -> None: reveal_type(b) # N: Revealed type is "__main__.B" [case testNarrowingNestedUnionOfTypedDicts] +# flags: --strict-equality --warn-unreachable from typing import Literal, TypedDict, Union class A(TypedDict): @@ -1406,6 +1432,7 @@ else: [typing fixtures/typing-typeddict.pyi] [case testNarrowingRuntimeCover] +# flags: --strict-equality --warn-unreachable from typing import Dict, List, Union def unreachable(x: Union[str, List[str]]) -> None: @@ -1414,7 +1441,7 @@ def unreachable(x: Union[str, List[str]]) -> None: elif isinstance(x, list): reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]" else: - reveal_type(x) # No output: this branch is unreachable + reveal_type(x) # No output: this branch is unreachable # E: Statement is unreachable def all_parts_covered(x: Union[str, List[str], List[int], int]) -> None: if isinstance(x, str): @@ -1435,6 +1462,7 @@ def two_type_vars(x: Union[str, Dict[str, int], Dict[bool, object], int]) -> Non [case testNarrowingWithDef] +# flags: --strict-equality --warn-unreachable from typing import Callable, Optional def g() -> None: @@ -1446,6 +1474,7 @@ def g() -> None: [case testNarrowingOptionalEqualsNone] +# flags: --strict-equality --warn-unreachable from typing import Optional class A: ... @@ -1489,6 +1518,7 @@ def f(x: Custom | None): [builtins fixtures/primitives.pyi] [case testNarrowingWithTupleOfTypes] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Type class Base: ... @@ -1513,7 +1543,7 @@ else: [case testNarrowingWithTupleOfTypesPy310Plus] -# flags: --python-version 3.10 +# flags: --python-version 3.10 --strict-equality --warn-unreachable class Base: ... class Impl1(Base): ... @@ -1535,6 +1565,7 @@ else: [builtins fixtures/dict.pyi] [case testNarrowingWithAnyOps] +# flags: --strict-equality --warn-unreachable from typing import Any class C: ... @@ -1578,6 +1609,7 @@ reveal_type(t) # N: Revealed type is "Any" [builtins fixtures/isinstancelist.pyi] [case testNarrowingLenItemAndLenCompare] +# flags: --strict-equality --warn-unreachable from typing import Any x: Any @@ -1586,6 +1618,7 @@ if len(x) == x: [builtins fixtures/len.pyi] [case testNarrowingLenTuple] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union VarTuple = Union[Tuple[int, int], Tuple[int, int, int]] @@ -1604,6 +1637,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenHomogeneousTuple] +# flags: --strict-equality --warn-unreachable from typing import Tuple x: Tuple[int, ...] @@ -1619,6 +1653,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenTypeUnaffected] +# flags: --strict-equality --warn-unreachable from typing import Union, List x: Union[str, List[int]] @@ -1629,6 +1664,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenAnyListElseNotAffected] +# flags: --strict-equality --warn-unreachable from typing import Any def f(self, value: Any) -> Any: @@ -1640,6 +1676,7 @@ def f(self, value: Any) -> Any: [builtins fixtures/len.pyi] [case testNarrowingLenMultiple] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union VarTuple = Union[Tuple[int, int], Tuple[int, int, int]] @@ -1652,6 +1689,7 @@ if len(x) == len(y) == 3: [builtins fixtures/len.pyi] [case testNarrowingLenFinal] +# flags: --strict-equality --warn-unreachable from typing import Final, Tuple, Union VarTuple = Union[Tuple[int, int], Tuple[int, int, int]] @@ -1663,6 +1701,7 @@ if len(x) == fin: [builtins fixtures/len.pyi] [case testNarrowingLenGreaterThan] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union VarTuple = Union[Tuple[int], Tuple[int, int], Tuple[int, int, int]] @@ -1690,6 +1729,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenBothSidesUnionTuples] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union VarTuple = Union[ @@ -1707,7 +1747,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenGreaterThanHomogeneousTupleShort] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple VarTuple = Tuple[int, ...] @@ -1721,7 +1761,7 @@ reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/len.pyi] [case testNarrowingLenBiggerThanHomogeneousTupleLong] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple VarTuple = Tuple[int, ...] @@ -1734,7 +1774,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenBothSidesHomogeneousTuple] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple x: Tuple[int, ...] @@ -1746,7 +1786,7 @@ reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/len.pyi] [case testNarrowingLenUnionTupleUnreachable] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union x: Union[Tuple[int, int], Tuple[int, int, int]] @@ -1762,6 +1802,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenMixedTypes] +# flags: --strict-equality --warn-unreachable from typing import Tuple, List, Union x: Union[Tuple[int, int], Tuple[int, int, int], List[int]] @@ -1782,6 +1823,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenTypeVarTupleEquals] +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import TypeVarTuple, Unpack @@ -1799,6 +1841,7 @@ def foo(x: Tuple[int, Unpack[Ts], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenTypeVarTupleGreaterThan] +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import TypeVarTuple, Unpack @@ -1827,7 +1870,7 @@ def foo(x: Tuple[int, Unpack[Ts], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenTypeVarTupleUnreachable] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import TypeVarTuple, Unpack @@ -1856,6 +1899,7 @@ def bar(x: Tuple[int, Unpack[Ts], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenVariadicTupleEquals] +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import Unpack @@ -1872,6 +1916,7 @@ def foo(x: Tuple[int, Unpack[Tuple[float, ...]], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenVariadicTupleGreaterThan] +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import Unpack @@ -1890,7 +1935,7 @@ def foo(x: Tuple[int, Unpack[Tuple[float, ...]], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenVariadicTupleUnreachable] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import Unpack @@ -1918,7 +1963,7 @@ def bar(x: Tuple[int, Unpack[Tuple[float, ...]], str]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenBareExpressionPrecise] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple x: Tuple[int, ...] @@ -1927,6 +1972,7 @@ reveal_type(x) # N: Revealed type is "tuple[builtins.int, Unpack[builtins.tuple [builtins fixtures/len.pyi] [case testNarrowingLenBareExpressionTypeVarTuple] +# flags: --strict-equality --warn-unreachable from typing import Tuple from typing_extensions import TypeVarTuple, Unpack @@ -1937,7 +1983,7 @@ def test(*xs: Unpack[Ts]) -> None: [builtins fixtures/len.pyi] [case testNarrowingLenBareExpressionWithNonePrecise] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple, Optional x: Optional[Tuple[int, ...]] @@ -1948,6 +1994,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenBareExpressionWithNoneImprecise] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Optional x: Optional[Tuple[int, ...]] @@ -1958,7 +2005,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenMixWithAnyPrecise] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Any x: Any @@ -1977,6 +2024,7 @@ reveal_type(x1) # N: Revealed type is "Any" [builtins fixtures/len.pyi] [case testNarrowingLenMixWithAnyImprecise] +# flags: --strict-equality --warn-unreachable from typing import Any x: Any @@ -1995,6 +2043,7 @@ reveal_type(x1) # N: Revealed type is "Any" [builtins fixtures/len.pyi] [case testNarrowingLenExplicitLiteralTypes] +# flags: --strict-equality --warn-unreachable from typing import Literal, Tuple, Union VarTuple = Union[ @@ -2018,6 +2067,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenUnionOfVariadicTuples] +# flags: --strict-equality --warn-unreachable from typing import Tuple, Union x: Union[Tuple[int, ...], Tuple[str, ...]] @@ -2028,6 +2078,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenUnionOfNamedTuples] +# flags: --strict-equality --warn-unreachable from typing import NamedTuple, Union class Point2D(NamedTuple): @@ -2046,6 +2097,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenTupleSubclass] +# flags: --strict-equality --warn-unreachable from typing import Tuple class Ints(Tuple[int, ...]): @@ -2063,6 +2115,7 @@ reveal_type(x) # N: Revealed type is "__main__.Ints" [builtins fixtures/len.pyi] [case testNarrowingLenTupleSubclassCustomNotAllowed] +# flags: --strict-equality --warn-unreachable from typing import Tuple class Ints(Tuple[int, ...]): @@ -2077,7 +2130,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenTupleSubclassPreciseNotAllowed] -# flags: --enable-incomplete-feature=PreciseTupleTypes +# flags: --enable-incomplete-feature=PreciseTupleTypes --strict-equality --warn-unreachable from typing import Tuple class Ints(Tuple[int, ...]): @@ -2091,6 +2144,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenUnknownLen] +# flags: --strict-equality --warn-unreachable from typing import Any, Tuple, Union x: Union[Tuple[int, int], Tuple[int, int, int]] @@ -2109,6 +2163,7 @@ else: [builtins fixtures/len.pyi] [case testNarrowingLenUnionWithUnreachable] +# flags: --strict-equality --warn-unreachable from typing import Union, Sequence def f(x: Union[int, Sequence[int]]) -> None: @@ -2122,6 +2177,7 @@ def f(x: Union[int, Sequence[int]]) -> None: [builtins fixtures/len.pyi] [case testNarrowingIsSubclassNoneType1] +# flags: --strict-equality --warn-unreachable from typing import Type, Union def f(cls: Type[Union[None, int]]) -> None: @@ -2132,6 +2188,7 @@ def f(cls: Type[Union[None, int]]) -> None: [builtins fixtures/isinstance.pyi] [case testNarrowingIsSubclassNoneType2] +# flags: --strict-equality --warn-unreachable from typing import Type, Union def f(cls: Type[Union[None, int]]) -> None: @@ -2142,6 +2199,7 @@ def f(cls: Type[Union[None, int]]) -> None: [builtins fixtures/isinstance.pyi] [case testNarrowingIsSubclassNoneType3] +# flags: --strict-equality --warn-unreachable from typing import Type, Union NoneType_ = type(None) @@ -2154,7 +2212,7 @@ def f(cls: Type[Union[None, int]]) -> None: [builtins fixtures/isinstance.pyi] [case testNarrowingIsSubclassNoneType4] -# flags: --python-version 3.10 +# flags: --python-version 3.10 --strict-equality --warn-unreachable from types import NoneType from typing import Type, Union @@ -2167,7 +2225,7 @@ def f(cls: Type[Union[None, int]]) -> None: [builtins fixtures/isinstance.pyi] [case testNarrowingIsInstanceNoIntersectionWithFinalTypeAndNoneType] -# flags: --warn-unreachable --python-version 3.10 +# flags: --warn-unreachable --python-version 3.10 --strict-equality from types import NoneType from typing import final @@ -2192,7 +2250,7 @@ if isinstance(x, (Z, NoneType)): # E: Subclass of "X" and "Z" cannot exist: "Z" [builtins fixtures/isinstance.pyi] [case testTypeNarrowingReachableNegative] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Literal x: Literal[-1] @@ -2204,6 +2262,7 @@ if x == -1: [builtins fixtures/ops.pyi] [case testTypeNarrowingReachableNegativeUnion] +# flags: --strict-equality --warn-unreachable from typing import Literal x: Literal[-1, 1] @@ -2345,6 +2404,7 @@ def f8(x: IE | None) -> None: [builtins fixtures/primitives.pyi] [case testNarrowingWithStrEnum] +# flags: --strict-equality --warn-unreachable # mypy: strict-equality from enum import StrEnum @@ -2399,7 +2459,7 @@ def foo(location: ParameterLocation): [builtins fixtures/primitives.pyi] [case testConsistentNarrowingEqAndIn] -# flags: --python-version 3.10 +# flags: --python-version 3.10 --strict-equality --warn-unreachable # https://github.com/python/mypy/issues/17864 def f(x: str | int) -> None: @@ -2415,7 +2475,7 @@ def f(x: str | int) -> None: [builtins fixtures/primitives.pyi] [case testConsistentNarrowingEqAndInWithCustomEq] -# flags: --python-version 3.10 +# flags: --python-version 3.10 --strict-equality --warn-unreachable # https://github.com/python/mypy/issues/17864 class C: @@ -2446,7 +2506,7 @@ f2(C(5)) [builtins fixtures/primitives.pyi] [case testNarrowingTypeVarNone] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable # https://github.com/python/mypy/issues/18126 from typing import TypeVar @@ -2465,7 +2525,7 @@ def fn_while(arg: T) -> None: [builtins fixtures/primitives.pyi] [case testRefinePartialTypeWithinLoop] -# flags: --no-local-partial-types +# flags: --no-local-partial-types --strict-equality --warn-unreachable x = None for _ in range(2): @@ -2501,7 +2561,7 @@ class A: [builtins fixtures/primitives.pyi] [case testPersistentUnreachableLinesNestedInInpersistentUnreachableLines] -# flags: --warn-unreachable --python-version 3.11 +# flags: --warn-unreachable --python-version 3.11 --strict-equality x = None y = None @@ -2513,7 +2573,7 @@ while True: [builtins fixtures/bool.pyi] [case testAvoidFalseRedundantCastInLoops] -# flags: --warn-redundant-casts +# flags: --warn-redundant-casts --strict-equality --warn-unreachable from typing import Callable, cast, Union @@ -2534,7 +2594,7 @@ def main_no_cast(p: Processor) -> None: [builtins fixtures/bool.pyi] [case testAvoidFalseUnreachableInLoop1] -# flags: --warn-unreachable --python-version 3.11 +# flags: --warn-unreachable --python-version 3.11 --strict-equality def f() -> int | None: ... def b() -> bool: ... @@ -2546,7 +2606,7 @@ while x is not None or b(): [builtins fixtures/bool.pyi] [case testAvoidFalseUnreachableInLoop2] -# flags: --warn-unreachable --python-version 3.11 +# flags: --warn-unreachable --python-version 3.11 --strict-equality y = None while y is None: @@ -2556,7 +2616,7 @@ while y is None: [builtins fixtures/list.pyi] [case testAvoidFalseUnreachableInLoop3] -# flags: --warn-unreachable --python-version 3.11 +# flags: --warn-unreachable --python-version 3.11 --strict-equality xs: list[int | None] y = None @@ -2567,7 +2627,7 @@ for x in xs: [builtins fixtures/list.pyi] [case testAvoidFalseRedundantExprInLoop] -# flags: --enable-error-code redundant-expr --python-version 3.11 +# flags: --enable-error-code redundant-expr --python-version 3.11 --strict-equality --warn-unreachable def f() -> int | None: ... def b() -> bool: ... @@ -2579,7 +2639,7 @@ while x is not None and b(): [builtins fixtures/primitives.pyi] [case testAvoidFalseNonOverlappingEqualityCheckInLoop1] -# flags: --allow-redefinition-new --local-partial-types --strict-equality +# flags: --allow-redefinition-new --local-partial-types --strict-equality --warn-unreachable x = 1 while True: @@ -2591,7 +2651,7 @@ while True: [builtins fixtures/primitives.pyi] [case testAvoidFalseNonOverlappingEqualityCheckInLoop2] -# flags: --allow-redefinition-new --local-partial-types --strict-equality +# flags: --allow-redefinition-new --local-partial-types --strict-equality --warn-unreachable class A: ... class B: ... @@ -2605,15 +2665,16 @@ while True: [builtins fixtures/primitives.pyi] [case testAvoidFalseNonOverlappingEqualityCheckInLoop3] -# flags: --strict-equality +# flags: --strict-equality --warn-unreachable for y in [1.0]: - if y is not None or y != "None": + if y is not None or y != "None": # E: Right operand of "or" is never evaluated ... [builtins fixtures/primitives.pyi] [case testNarrowPromotionsInsideUnions1] +# flags: --strict-equality --warn-unreachable from typing import Union @@ -2628,7 +2689,7 @@ reveal_type(z) # N: Revealed type is "builtins.int | builtins.str" [builtins fixtures/primitives.pyi] [case testNarrowPromotionsInsideUnions2] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Optional @@ -2647,7 +2708,7 @@ while b(): [builtins fixtures/bool.pyi] [case testAvoidFalseUnreachableInFinally] -# flags: --allow-redefinition-new --local-partial-types --warn-unreachable +# flags: --allow-redefinition-new --local-partial-types --strict-equality --warn-unreachable def f() -> None: try: x = 1 @@ -2666,6 +2727,7 @@ def f() -> None: [builtins fixtures/isinstancelist.pyi] [case testNarrowingTypeVarMultiple] +# flags: --strict-equality --warn-unreachable from typing import TypeVar class A: ... @@ -2684,6 +2746,7 @@ def foo(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testDoNotNarrowToNever] +# flags: --strict-equality --warn-unreachable def any(): return 1 @@ -2695,6 +2758,7 @@ def f() -> None: [builtins fixtures/isinstance.pyi] [case testNarrowTypeVarBoundType] +# flags: --strict-equality --warn-unreachable from typing import Type, TypeVar class A: ... @@ -2711,6 +2775,7 @@ def test(cls: Type[T]) -> T: [builtins fixtures/isinstance.pyi] [case testNarrowTypeVarBoundUnion] +# flags: --strict-equality --warn-unreachable from typing import TypeVar class A: @@ -2734,6 +2799,7 @@ def test(x: T) -> T: [builtins fixtures/isinstance.pyi] [case testIsinstanceNarrowingWithSelfTypes] +# flags: --strict-equality --warn-unreachable from typing import Generic, TypeVar, overload T = TypeVar("T") @@ -2786,12 +2852,13 @@ class D(tuple[T], Generic[T]): ... def check_d(arg: D[T]) -> None: if not isinstance(arg, D): - return + return # E: Statement is unreachable reveal_type(arg) # N: Revealed type is "tuple[T`-1, fallback=__main__.D[Any]]" [builtins fixtures/tuple.pyi] [case testNarrowingUnionMixins] +# flags: --strict-equality --warn-unreachable class Base: ... class FooMixin: @@ -2814,6 +2881,7 @@ def baz(item: Base) -> None: [builtins fixtures/isinstance.pyi] [case testCustomSetterNarrowingReWidened] +# flags: --strict-equality --warn-unreachable class B: ... class C(B): ... class C1(B): ... @@ -2833,7 +2901,7 @@ reveal_type(t.foo) # N: Revealed type is "__main__.C" [builtins fixtures/property.pyi] [case testNarrowingNotImplemented] -# flags: --python-version 3.10 +# flags: --python-version 3.10 --warn-unreachable from __future__ import annotations import types @@ -2855,7 +2923,7 @@ class X: [case testNarrowingBooleans] -# flags: --warn-return-any +# flags: --warn-return-any --strict-equality --warn-unreachable from typing import Any def foo(x: dict[str, Any]) -> bool: @@ -2868,7 +2936,7 @@ def foo(x: dict[str, Any]) -> bool: [case testNarrowingTypeObjects] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from __future__ import annotations from typing import Callable, Any, TypeVar, Generic, Protocol _T_co = TypeVar('_T_co', covariant=True) @@ -2902,7 +2970,7 @@ def main(key: str): [builtins fixtures/tuple.pyi] [case testNarrowingCollections] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import cast class X: @@ -2919,7 +2987,7 @@ class X: reveal_type(self.x) # N: Revealed type is "builtins.dict[builtins.str, builtins.str]" self.x["asdf"] - if self.x == cast(dict[int, int], {}): + if self.x == cast(dict[int, int], {}): # E: Non-overlapping equality check (left operand type: "dict[str, str]", right operand type: "dict[int, int]") reveal_type(self.x) # N: Revealed type is "builtins.dict[builtins.str, builtins.str]" self.x["asdf"] @@ -2932,7 +3000,7 @@ class X: reveal_type(self.y) # N: Revealed type is "builtins.list[builtins.str]" self.y[0].does_not_exist # E: "str" has no attribute "does_not_exist" - if self.y == cast(list[int], []): + if self.y == cast(list[int], []): # E: Non-overlapping equality check (left operand type: "list[str]", right operand type: "list[int]") reveal_type(self.y) # N: Revealed type is "builtins.list[builtins.str]" self.y[0].does_not_exist # E: "str" has no attribute "does_not_exist" [builtins fixtures/dict.pyi] @@ -3006,6 +3074,7 @@ def f1(x: Union[str, float], t1: list[Literal['a', 'b']], t2: list[str]): [builtins fixtures/primitives.pyi] [case testNarrowAnyWithEqualityOrContainment] +# flags: --strict-equality --warn-unreachable # https://github.com/python/mypy/issues/17841 from typing import Any @@ -3169,7 +3238,7 @@ def main(x: Union[B, C]): [builtins fixtures/isinstance.pyi] [case testTypeEqualsCheckUsingDifferentSpecializedTypes] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from collections import defaultdict x: defaultdict @@ -3199,7 +3268,7 @@ def f(x: Any): [builtins fixtures/tuple.pyi] [case testTypeIntersectionWithConcreteTypes] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable class X: x = 1 class Y: y = 1 class Z(X, Y): ... @@ -3207,7 +3276,7 @@ class Z(X, Y): ... z = Z() x: X = z y: Y = z -if type(x) is type(y): +if type(x) is type(y): # E: Non-overlapping identity check (left operand type: "type[X]", right operand type: "type[Y]") reveal_type(x) # N: Revealed type is "__main__." reveal_type(y) # N: Revealed type is "__main__." x.y + y.x @@ -3322,7 +3391,7 @@ else: reveal_type(x) # N: Revealed type is "__main__.C" [case testDunderClassNarrowing] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Any def foo(y: object): diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 3abf5673fa66..7482836b9730 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -45,17 +45,18 @@ match m: [builtins fixtures/primitives.pyi] [case testMatchLiteralPatternUnreachable] -# primitives are needed because otherwise mypy doesn't see that int and str are incompatible +# flags: --strict-equality --warn-unreachable m: int match m: case "str": - reveal_type(m) + reveal_type(m) # E: Statement is unreachable [builtins fixtures/primitives.pyi] -- Value Pattern -- [case testMatchValuePatternNarrows] +# flags: --strict-equality --warn-unreachable import b m: object @@ -66,6 +67,7 @@ match m: b: int [case testMatchValuePatternAlreadyNarrower] +# flags: --strict-equality --warn-unreachable import b m: bool @@ -76,6 +78,7 @@ match m: b: int [case testMatchValuePatternIntersect] +# flags: --strict-equality --warn-unreachable import b class A: ... @@ -89,7 +92,7 @@ class B: ... b: B [case testMatchValuePatternUnreachable] -# primitives are needed because otherwise mypy doesn't see that int and str are incompatible +# flags: --strict-equality --warn-unreachable import b m: int @@ -491,6 +494,7 @@ b: str [builtins fixtures/dict.pyi] [case testMatchMappingPatternCapturesWrongKeyType] +# flags: --strict-equality --warn-unreachable # This is not actually unreachable, as a subclass of dict could accept keys with different types from typing import Dict import b @@ -572,6 +576,7 @@ a: str [typing fixtures/typing-typeddict.pyi] [case testMatchMappingPatternCapturesTypedDictUnreachable] +# flags: --strict-equality --warn-unreachable # TypedDict keys are always str, so this is actually unreachable from typing import TypedDict import b @@ -584,9 +589,9 @@ m: A match m: case {1: v}: - reveal_type(v) + reveal_type(v) # E: Statement is unreachable case {b.b: v2}: - reveal_type(v2) + reveal_type(v2) # E: Statement is unreachable [file b.py] b: int [typing fixtures/typing-typeddict.pyi] @@ -1099,7 +1104,7 @@ match m: pass [case testMatchClassPatternCallable] -# flags: --warn-unreachable +# flags: --strict-equality --warn-unreachable from typing import Callable, Any class FnImpl: @@ -1542,11 +1547,12 @@ match m: [builtins fixtures/isinstancelist.pyi] [case testMatchUnreachablePatternGuard] +# flags: --strict-equality --warn-unreachable m: str match m: - case a if isinstance(a, int): - reveal_type(a) + case a if isinstance(a, int): # E: Subclass of "str" and "int" cannot exist: would have incompatible method signatures + reveal_type(a) # E: Statement is unreachable [builtins fixtures/isinstancelist.pyi] [case testMatchSubjectAssignExprWithGuard]