From ff134e6467064c2abe53a52a891cc0830ea40a2e Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sun, 2 Apr 2023 08:34:28 -0700 Subject: [PATCH] Added documentation to mypy comparison that talks about narrowing for captured variables. --- docs/mypy-comparison.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/mypy-comparison.md b/docs/mypy-comparison.md index eb9bb1083..3ee5cda4d 100644 --- a/docs/mypy-comparison.md +++ b/docs/mypy-comparison.md @@ -177,6 +177,25 @@ def is_red(color: Color) -> bool: # mypy reports error: Missing return statement ``` +### Narrowing for Captured Variables + +If a variable’s type is narrowed in an outer scope and the variable is subsequently used within an inner-scoped function or lambda, mypy does not retain the narrowed type within the inner scope. Pyright retains the narrowed type if it can determine that the value of the captured variable is not modified on any code path after the inner-scope function or lambda is defined. + +```python +def func(val: int | None): + if val is not None: + + def inner_1() -> None: + reveal_type(val) # pyright: int, mypy: int | None + print(val + 1) # mypy produces a false positive error here + + inner_2 = lambda: reveal_type(val) + 1 # pyright: int, mypy: int | None + + inner_1() + inner_2() +``` + + ### Narrowing Any Pyright never narrows `Any` when performing type narrowing for assignments. Mypy is inconsistent about when it applies type narrowing to `Any` type arguments.