From 6cd8655d29dd11a3411217f7e4ea9c82b03dcb54 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 23 Nov 2022 20:28:37 -0500 Subject: [PATCH] Treat withitem variables as bindings (#897) --- resources/test/fixtures/F841.py | 8 ++++++++ src/check_ast.rs | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/resources/test/fixtures/F841.py b/resources/test/fixtures/F841.py index c5b2583163..cef1a76a58 100644 --- a/resources/test/fixtures/F841.py +++ b/resources/test/fixtures/F841.py @@ -57,3 +57,11 @@ def f5(): def f6(): annotations = [] assert len([annotations for annotations in annotations]) + + +def f7(): + def connect(): + return None, None + + with connect() as (connection, cursor): + cursor.execute("SELECT * FROM users") diff --git a/src/check_ast.rs b/src/check_ast.rs index f32d8b26da..91eff2c844 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -6,6 +6,7 @@ use std::path::Path; use itertools::Itertools; use log::error; use rustc_hash::{FxHashMap, FxHashSet}; +use rustpython_ast::Withitem; use rustpython_parser::ast::{ Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, KeywordData, Operator, Stmt, StmtKind, Suite, @@ -21,7 +22,7 @@ use crate::ast::types::{ Binding, BindingContext, BindingKind, ClassScope, FunctionScope, ImportKind, Range, Scope, ScopeKind, }; -use crate::ast::visitor::{walk_excepthandler, Visitor}; +use crate::ast::visitor::{walk_excepthandler, walk_withitem, Visitor}; use crate::ast::{helpers, operations, visitor}; use crate::checks::{Check, CheckCode, CheckKind}; use crate::docstrings::definition::{Definition, DefinitionKind, Documentable}; @@ -77,6 +78,7 @@ pub struct Checker<'a> { in_deferred_string_annotation: bool, in_literal: bool, in_subscript: bool, + in_withitem: bool, seen_import_boundary: bool, futures_allowed: bool, annotations_future_enabled: bool, @@ -120,6 +122,7 @@ impl<'a> Checker<'a> { in_deferred_string_annotation: false, in_literal: false, in_subscript: false, + in_withitem: false, seen_import_boundary: false, futures_allowed: true, annotations_future_enabled: false, @@ -2080,6 +2083,13 @@ where self.check_builtin_arg_shadowing(&arg.node.arg, Range::from_located(arg)); } + + fn visit_withitem(&mut self, withitem: &'b Withitem) { + let prev_in_withitem = self.in_withitem; + self.in_withitem = true; + walk_withitem(self, withitem); + self.in_withitem = prev_in_withitem; + } } fn try_mark_used(scope: &mut Scope, scope_id: usize, id: &str, expr: &Expr) -> bool { @@ -2386,7 +2396,7 @@ impl<'a> Checker<'a> { return; } - if operations::is_unpacking_assignment(parent) { + if self.in_withitem || operations::is_unpacking_assignment(parent) { self.add_binding( id, Binding {