Treat withitem variables as bindings (#897)

This commit is contained in:
Charlie Marsh 2022-11-23 20:28:37 -05:00 committed by GitHub
parent 72a9bd3cfb
commit 6cd8655d29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 2 deletions

View file

@ -57,3 +57,11 @@ def f5():
def f6(): def f6():
annotations = [] annotations = []
assert len([annotations for annotations in 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")

View file

@ -6,6 +6,7 @@ use std::path::Path;
use itertools::Itertools; use itertools::Itertools;
use log::error; use log::error;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_ast::Withitem;
use rustpython_parser::ast::{ use rustpython_parser::ast::{
Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind,
KeywordData, Operator, Stmt, StmtKind, Suite, KeywordData, Operator, Stmt, StmtKind, Suite,
@ -21,7 +22,7 @@ use crate::ast::types::{
Binding, BindingContext, BindingKind, ClassScope, FunctionScope, ImportKind, Range, Scope, Binding, BindingContext, BindingKind, ClassScope, FunctionScope, ImportKind, Range, Scope,
ScopeKind, 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::ast::{helpers, operations, visitor};
use crate::checks::{Check, CheckCode, CheckKind}; use crate::checks::{Check, CheckCode, CheckKind};
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable}; use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
@ -77,6 +78,7 @@ pub struct Checker<'a> {
in_deferred_string_annotation: bool, in_deferred_string_annotation: bool,
in_literal: bool, in_literal: bool,
in_subscript: bool, in_subscript: bool,
in_withitem: bool,
seen_import_boundary: bool, seen_import_boundary: bool,
futures_allowed: bool, futures_allowed: bool,
annotations_future_enabled: bool, annotations_future_enabled: bool,
@ -120,6 +122,7 @@ impl<'a> Checker<'a> {
in_deferred_string_annotation: false, in_deferred_string_annotation: false,
in_literal: false, in_literal: false,
in_subscript: false, in_subscript: false,
in_withitem: false,
seen_import_boundary: false, seen_import_boundary: false,
futures_allowed: true, futures_allowed: true,
annotations_future_enabled: false, annotations_future_enabled: false,
@ -2080,6 +2083,13 @@ where
self.check_builtin_arg_shadowing(&arg.node.arg, Range::from_located(arg)); 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 { fn try_mark_used(scope: &mut Scope, scope_id: usize, id: &str, expr: &Expr) -> bool {
@ -2386,7 +2396,7 @@ impl<'a> Checker<'a> {
return; return;
} }
if operations::is_unpacking_assignment(parent) { if self.in_withitem || operations::is_unpacking_assignment(parent) {
self.add_binding( self.add_binding(
id, id,
Binding { Binding {