Repository: pylint-dev/pylint

Issue:
False positive `used-before-assignment` with try/else/continue
### Bug description

The `used-before-assignment` check reports a false positive with try/else/continue starting with pylint 2.13.0.

This issue is nearly identical to https://github.com/PyCQA/pylint/issues/6790, except it involves `continue` instead of `return`.

```python
"""bug.py"""


def demo():
    """Demonstrate used-before-assignment regression in pylint==2.13.0 and 2.14.0."""
    for _temp in range(0, 1):
        try:
            pass
        except ValueError:
            error = True
        else:
            continue

        print(error)
```

### Configuration

_No response_

### Command used

```shell
pylint bug.py
```


### Pylint output

```shell
************* Module bug
bug.py:14:14: E0601: Using variable 'error' before assignment (used-before-assignment)
```


### Expected behavior

No errors reported, as was the case for 2.12.2.

### Pylint version

```shell
pylint 2.14.0
astroid 2.11.5
Python 3.9.5 (default, Nov 23 2021, 15:27:38) 
[GCC 9.3.0]
```


### OS / Environment

Ubuntu 22.04.4

### Additional dependencies

_No response_


Discussion:
This one's harder because depending on `error` is not safe if attempted outside the loop, so my hope would be to distinguish the two cases.



Patch:
diff --git a/doc/whatsnew/fragments/6804.false_positive b/doc/whatsnew/fragments/6804.false_positive
new file mode 100644
index 0000000000..9069ec35bd
--- /dev/null
+++ b/doc/whatsnew/fragments/6804.false_positive
@@ -0,0 +1,5 @@
+``used-before-assignment`` is no longer emitted when using a name in a loop and
+depending on an earlier name assignment in an ``except`` block paired with
+``else: continue``.
+
+Closes #6804
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 925088f60d..b13e25491a 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -883,6 +883,16 @@ def _uncertain_nodes_in_except_blocks(
                 and utils.is_terminating_func(else_statement.value)
                 for else_statement in closest_try_except.orelse
             )
+            else_block_continues = any(
+                isinstance(else_statement, nodes.Continue)
+                for else_statement in closest_try_except.orelse
+            )
+            if (
+                else_block_continues
+                and isinstance(node_statement.parent, (nodes.For, nodes.While))
+                and closest_try_except.parent.parent_of(node_statement)
+            ):
+                continue
 
             if try_block_returns or else_block_returns or else_block_exits:
                 # Exception: if this node is in the final block of the other_node_statement,


Test patch:
diff --git a/tests/functional/u/used/used_before_assignment_else_continue.py b/tests/functional/u/used/used_before_assignment_else_continue.py
new file mode 100644
index 0000000000..e147c5eed8
--- /dev/null
+++ b/tests/functional/u/used/used_before_assignment_else_continue.py
@@ -0,0 +1,42 @@
+"""If the else block continues, it is generally safe to rely on assignments in the except,
+inside the same for loop only."""
+
+
+def safe():
+    """Name used safely inside the loop."""
+    while True:
+        try:
+            pass
+        except ValueError:
+            error = True
+        else:
+            continue
+
+        print(error)
+
+
+def halfway_safe():
+    """Name used safely inside the loop, unsafely outside it."""
+    for _temp in range(0, 1):
+        try:
+            pass
+        except ValueError:
+            error = True
+        else:
+            continue
+
+        print(error)
+    print(error)  # https://github.com/pylint-dev/pylint/issues/9379
+
+
+def unsafe():
+    """Name used unsafely outside the loop."""
+    for _temp in range(0, 1):
+        try:
+            pass
+        except ValueError:
+            error = True
+        else:
+            continue
+
+    print(error)  # [used-before-assignment]
diff --git a/tests/functional/u/used/used_before_assignment_else_continue.txt b/tests/functional/u/used/used_before_assignment_else_continue.txt
new file mode 100644
index 0000000000..76e8c66a1d
--- /dev/null
+++ b/tests/functional/u/used/used_before_assignment_else_continue.txt
@@ -0,0 +1,1 @@
+used-before-assignment:42:10:42:15:unsafe:Using variable 'error' before assignment:CONTROL_FLOW