8000 Avoid false `unreachable` and `redundant-expr` warnings in loops. (#1… · sthagen/python-mypy@9685171 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9685171

Browse files
authored
Avoid false unreachable and redundant-expr warnings in loops. (python#18433)
Fixes python#18348 Fixes python#13973 Fixes python#11612 Fixes python#8721 Fixes python#8865 Fixes python#7204 I manually checked all the listed issues. Some of them were already partly fixed by python#18180.
1 parent 9274a07 commit 9685171

File tree

2 files changed

+50
-5
lines changed
  • mypy
    • < 8000 div class="PRIVATE_TreeView-item-container prc-TreeView-TreeViewItemContainer--2Rkn" style="--level:2">
  • test-data/unit
  • 2 files changed

    +50
    -5
    lines changed

    mypy/checker.py

    Lines changed: 24 additions & 5 deletions
    Original file line numberDiff line numberDiff line change
    @@ -584,24 +584,43 @@ def accept_loop(
    584584
    *,
    585585
    exit_condition: Expression | None = None,
    586586
    ) -> None:
    587-
    """Repeatedly type check a loop body until the frame doesn't change.
    588-
    If exit_condition is set, assume it must be False on exit from the loop.
    587+
    """Repeatedly type check a loop body until the frame doesn't change."""
    589588

    590-
    Then check the else_body.
    591-
    """
    592-
    # The outer frame accumulates the results of all iterations
    589+
    # The outer frame accumulates the results of all iterations:
    593590
    with self.binder.frame_context(can_skip=False, conditional_frame=True):
    591+
    592+
    # Check for potential decreases in the number of partial types so as not to stop the
    593+
    # iteration too early:
    594594
    partials_old = sum(len(pts.map) for pts in self.partial_types)
    595+
    596+
    # Disable error types that we cannot safely identify in intermediate iteration steps:
    597+
    warn_unreachable = self.options.warn_unreachable
    598+
    warn_redundant = codes.REDUNDANT_EXPR in self.options.enabled_error_codes
    599+
    self.options.warn_unreachable = False
    600+
    self.options.enabled_error_codes.discard(codes.REDUNDANT_EXPR)
    601+
    595602
    while True:
    596603
    with self.binder.frame_context(can_skip=True, break_frame=2, continue_frame=1):
    597604
    self.accept(body)
    598605
    partials_new = sum(len(pts.map) for pts in self.partial_types)
    599606
    if (partials_new == partials_old) and not self.binder.last_pop_changed:
    600607
    break
    601608
    partials_old = partials_new
    609+
    610+
    # If necessary, reset the modified options and make up for the postponed error checks:
    611+
    self.options.warn_unreachable = warn_unreachable
    612+
    if warn_redundant:
    613+
    self.options.enabled_error_codes.add(codes.REDUNDANT_EXPR)
    614+
    if warn_unreachable or warn_redundant:
    615+
    with self.binder.frame_context(can_skip=True, break_frame=2, continue_frame=1):
    616+
    self.accept(body)
    617+
    618+
    # If exit_condition is set, assume it must be False on exit from the loop:
    602619
    if exit_condition:
    603620
    _, else_map = self.find_isinstance_check(exit_condition)
    604621
    self.push_type_map(else_map)
    622+
    623+
    # Check the else body:
    605624
    if else_body:
    606625
    self.accept(else_body)
    607626

    test-data/unit/check-narrowing.test

    Lines changed: 26 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -2390,3 +2390,29 @@ class A:
    23902390
    z.append(1)
    23912391

    23922392
    [builtins fixtures/primitives.pyi]
    2393+
    2394+
    [case testAvoidFalseUnreachableInLoop]
    2395+
    # flags: --warn-unreachable --python-version 3.11
    2396+
    2397+
    def f() -> int | None: ...
    2398+
    def b() -> bool: ...
    2399+
    2400+
    x: int | None
    2401+
    x = 1
    2402+
    while x is not None or b():
    2403+
    x = f()
    2404+
    2405+
    [builtins fixtures/bool.pyi]
    2406+
    2407+
    [case testAvoidFalseRedundantExprInLoop]
    2408+
    # flags: --enable-error-code redundant-expr --python-version 3.11
    2409+
    2410+
    def f() -> int | None: ...
    2411+
    def b() -> bool: ...
    2412+
    2413+
    x: int | None
    2414+
    x = 1
    2415+
    while x is not None and b():
    2416+
    x = f()
    2417+
    2418+
    [builtins fixtures/primitives.pyi]

    0 commit comments

    Comments
     (0)
    0