Merge pull request #18030 from github/tausbn/python-fix-match-literal-pruning

Python: Fix pruning of literals in `match` pattern
This commit is contained in:
yoff 2024-11-19 17:16:22 +01:00 коммит произвёл GitHub
Родитель e5951516b8 e2530cf14f
Коммит d4ec8f650a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
2 изменённых файлов: 23 добавлений и 2 удалений

Просмотреть файл

@ -196,6 +196,25 @@ class SkippedVisitor(ASTVisitor):
if isinstance(node.value, ast.Name): if isinstance(node.value, ast.Name):
self.nodes.add(node.value) self.nodes.add(node.value)
class NotBooleanTestVisitor(ASTVisitor):
"""Visitor that checks if a test is not a boolean test."""
def __init__(self):
self.nodes = set()
def visit_MatchLiteralPattern(self, node):
# MatchLiteralPatterns _look_ like boolean tests, but are not.
# Thus, without this check, we would interpret
#
# match x:
# case False:
# pass
#
# (and similarly for True) as if it was a boolean test. This would cause the true edge
# (leading to pass) to be pruned later on.
if isinstance(node.literal, ast.Name) and node.literal.id in ('True', 'False'):
self.nodes.add(node.literal)
class NonlocalVisitor(ASTVisitor): class NonlocalVisitor(ASTVisitor):
def __init__(self): def __init__(self):
self.names = set() self.names = set()
@ -306,6 +325,8 @@ def effective_constants_definitions(bool_const_defns, graph, branching_edges):
def do_pruning(tree, graph): def do_pruning(tree, graph):
v = BoolConstVisitor() v = BoolConstVisitor()
v.visit(tree) v.visit(tree)
not_boolean_test = NotBooleanTestVisitor()
not_boolean_test.visit(tree)
nonlocals = NonlocalVisitor() nonlocals = NonlocalVisitor()
nonlocals.visit(tree) nonlocals.visit(tree)
global_vars = GlobalVisitor() global_vars = GlobalVisitor()
@ -353,6 +374,8 @@ def do_pruning(tree, graph):
b = const_value(pred.node) b = const_value(pred.node)
if b is None: if b is None:
continue continue
if pred.node in not_boolean_test.nodes:
continue
if b.contradicts(val): if b.contradicts(val):
to_be_removed.add((pred, succ)) to_be_removed.add((pred, succ))
if not to_be_removed: if not to_be_removed:

Просмотреть файл

@ -4,5 +4,3 @@
| test.py:21:5:21:38 | For | This statement is unreachable. | | test.py:21:5:21:38 | For | This statement is unreachable. |
| test.py:28:9:28:21 | ExprStmt | This statement is unreachable. | | test.py:28:9:28:21 | ExprStmt | This statement is unreachable. |
| test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. | | test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. |
| test.py:144:13:144:16 | Pass | This statement is unreachable. |
| test.py:147:9:148:16 | Case | This statement is unreachable. |