@@ -1373,13 +1373,13 @@ else:
13731373 reveal_type(val) # N: Revealed type is "None"
13741374
13751375if val in (None,):
1376- reveal_type(val) # N: Revealed type is "__main__.A | None"
1376+ reveal_type(val) # N: Revealed type is "None"
13771377else:
1378- reveal_type(val) # N: Revealed type is "__main__.A | None "
1378+ reveal_type(val) # N: Revealed type is "__main__.A"
13791379if val not in (None,):
1380- reveal_type(val) # N: Revealed type is "__main__.A | None "
1380+ reveal_type(val) # N: Revealed type is "__main__.A"
13811381else:
1382- reveal_type(val) # N: Revealed type is "__main__.A | None"
1382+ reveal_type(val) # N: Revealed type is "None"
13831383
13841384class Hmm:
13851385 def __eq__(self, other) -> bool: ...
@@ -2294,9 +2294,8 @@ def f(x: str | int) -> None:
22942294 y = x
22952295
22962296 if x in ["x"]:
2297- # TODO: we should fix this reveal https://github.com/python/mypy/issues/3229
2298- reveal_type(x) # N: Revealed type is "builtins.str | builtins.int"
2299- y = x # E: Incompatible types in assignment (expression has type "str | int", variable has type "str")
2297+ reveal_type(x) # N: Revealed type is "builtins.str"
2298+ y = x
23002299 z = x
23012300 z = y
23022301[builtins fixtures/primitives.pyi]
@@ -2806,3 +2805,126 @@ class X:
28062805 reveal_type(self.y) # N: Revealed type is "builtins.list[builtins.str]"
28072806 self.y[0].does_not_exist # E: "str" has no attribute "does_not_exist"
28082807[builtins fixtures/dict.pyi]
2808+
2809+
2810+ [case testTypeNarrowingStringInLiteralUnion]
2811+ from typing import Literal, Tuple
2812+ typ: Tuple[Literal['a', 'b'], ...] = ('a', 'b')
2813+ x: str = "hi!"
2814+ if x in typ:
2815+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2816+ else:
2817+ reveal_type(x) # N: Revealed type is "builtins.str"
2818+ [builtins fixtures/tuple.pyi]
2819+ [typing fixtures/typing-medium.pyi]
2820+
2821+ [case testTypeNarrowingStringInLiteralUnionSubset]
2822+ from typing import Literal, Tuple
2823+ typeAlpha: Tuple[Literal['a', 'b', 'c'], ...] = ('a', 'b')
2824+ strIn: str = "b"
2825+ strOut: str = "c"
2826+ if strIn in typeAlpha:
2827+ reveal_type(strIn) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']"
2828+ else:
2829+ reveal_type(strIn) # N: Revealed type is "builtins.str"
2830+ if strOut in typeAlpha:
2831+ reveal_type(strOut) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']"
2832+ else:
2833+ reveal_type(strOut) # N: Revealed type is "builtins.str"
2834+ [builtins fixtures/primitives.pyi]
2835+ [typing fixtures/typing-medium.pyi]
2836+
2837+ [case testNarrowingStringNotInLiteralUnion]
2838+ from typing import Literal, Tuple
2839+ typeAlpha: Tuple[Literal['a', 'b', 'c'],...] = ('a', 'b', 'c')
2840+ strIn: str = "c"
2841+ strOut: str = "d"
2842+ if strIn not in typeAlpha:
2843+ reveal_type(strIn) # N: Revealed type is "builtins.str"
2844+ else:
2845+ reveal_type(strIn) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']"
2846+ if strOut in typeAlpha:
2847+ reveal_type(strOut) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']"
2848+ else:
2849+ reveal_type(strOut) # N: Revealed type is "builtins.str"
2850+ [builtins fixtures/primitives.pyi]
2851+ [typing fixtures/typing-medium.pyi]
2852+
2853+ [case testNarrowingStringInLiteralUnionDontExpand]
2854+ from typing import Literal, Tuple
2855+ typeAlpha: Tuple[Literal['a', 'b', 'c'], ...] = ('a', 'b', 'c')
2856+ strIn: Literal['c'] = "c"
2857+ reveal_type(strIn) # N: Revealed type is "Literal['c']"
2858+ #Check we don't expand a Literal into the Union type
2859+ if strIn not in typeAlpha:
2860+ reveal_type(strIn) # N: Revealed type is "Literal['c']"
2861+ else:
2862+ reveal_type(strIn) # N: Revealed type is "Literal['c']"
2863+ [builtins fixtures/primitives.pyi]
2864+ [typing fixtures/typing-medium.pyi]
2865+
2866+ [case testTypeNarrowingStringInMixedUnion]
2867+ from typing import Literal, Tuple
2868+ typ: Tuple[Literal['a', 'b'], ...] = ('a', 'b')
2869+ x: str = "hi!"
2870+ if x in typ:
2871+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2872+ else:
2873+ reveal_type(x) # N: Revealed type is "builtins.str"
2874+ [builtins fixtures/tuple.pyi]
2875+ [typing fixtures/typing-medium.pyi]
2876+
2877+ [case testTypeNarrowingStringInSet]
2878+ from typing import Literal, Set
2879+ typ: Set[Literal['a', 'b']] = {'a', 'b'}
2880+ x: str = "hi!"
2881+ if x in typ:
2882+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2883+ else:
2884+ reveal_type(x) # N: Revealed type is "builtins.str"
2885+ if x not in typ:
2886+ reveal_type(x) # N: Revealed type is "builtins.str"
2887+ else:
2888+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2889+ [builtins fixtures/narrowing.pyi]
2890+ [typing fixtures/typing-medium.pyi]
2891+
2892+ [case testTypeNarrowingStringInList]
2893+ from typing import Literal, List
2894+ typ: List[Literal['a', 'b']] = ['a', 'b']
2895+ x: str = "hi!"
2896+ if x in typ:
2897+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2898+ else:
2899+ reveal_type(x) # N: Revealed type is "builtins.str"
2900+ if x not in typ:
2901+ reveal_type(x) # N: Revealed type is "builtins.str"
2902+ else:
2903+ reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']"
2904+ [builtins fixtures/narrowing.pyi]
2905+ [typing fixtures/typing-medium.pyi]
2906+
2907+ [case testTypeNarrowingUnionStringFloat]
2908+ from typing import Union
2909+ def foobar(foo: Union[str, float]):
2910+ if foo in ['a', 'b']:
2911+ reveal_type(foo) # N: Revealed type is "builtins.str"
2912+ else:
2913+ reveal_type(foo) # N: Revealed type is "builtins.str | builtins.float"
2914+ [builtins fixtures/primitives.pyi]
2915+ [typing fixtures/typing-medium.pyi]
2916+
2917+ [case testNarrowAnyWithEqualityOrContainment]
2918+ # https://github.com/python/mypy/issues/17841
2919+ from typing import Any
2920+
2921+ def f1(x: Any) -> None:
2922+ if x is not None and x not in ["x"]:
2923+ return
2924+ reveal_type(x) # N: Revealed type is "Any"
2925+
2926+ def f2(x: Any) -> None:
2927+ if x is not None and x != "x":
2928+ return
2929+ reveal_type(x) # N: Revealed type is "Any"
2930+ [builtins fixtures/tuple.pyi]
0 commit comments