Skip to content

Commit f17282d

Browse files
Skip class scopes when resolving nonlocal references (#4943)
1 parent 6950c93 commit f17282d

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

crates/ruff/resources/test/fixtures/pyflakes/F841_0.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,22 @@ def f(x: int):
126126
def f():
127127
if any((key := (value := x)) for x in ["ok"]):
128128
print(key)
129+
130+
131+
def f() -> None:
132+
is_connected = False
133+
134+
class Foo:
135+
@property
136+
def is_connected(self):
137+
nonlocal is_connected
138+
return is_connected
139+
140+
def do_thing(self):
141+
# This should resolve to the `is_connected` in the function scope.
142+
nonlocal is_connected
143+
print(is_connected)
144+
145+
obj = Foo()
146+
obj.do_thing()
147+

crates/ruff/src/checkers/ast/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,14 @@ where
291291
}
292292

293293
// Mark the binding in the defining scopes as used too. (Skip the global scope
294-
// and the current scope.)
294+
// and the current scope, and, per standard resolution rules, any class scopes.)
295295
for (name, range) in names.iter().zip(ranges.iter()) {
296296
let binding_id = self
297297
.semantic_model
298298
.scopes
299299
.ancestors(self.semantic_model.scope_id)
300300
.skip(1)
301-
.take_while(|scope| !scope.kind.is_module())
301+
.filter(|scope| !(scope.kind.is_module() || scope.kind.is_class()))
302302
.find_map(|scope| scope.get(name.as_str()));
303303

304304
if let Some(binding_id) = binding_id {

0 commit comments

Comments
 (0)