mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:16 +00:00
respect annotation-only declarations in infer_place_load
This commit is contained in:
parent
893f5727e5
commit
3b4667ec32
2 changed files with 10 additions and 10 deletions
|
@ -31,17 +31,17 @@ def f():
|
||||||
reveal_type(x) # revealed: Unknown | Literal[1]
|
reveal_type(x) # revealed: Unknown | Literal[1]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Skips annotation-only assignment
|
## Reads respect annotation-only declarations
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def f():
|
def f():
|
||||||
x = 1
|
x: int = 1
|
||||||
def g():
|
def g():
|
||||||
# it's pretty weird to have an annotated assignment in a function where the
|
# TODO: This example should actually be an unbound variable error. However to avoid false
|
||||||
# name is otherwise not defined; maybe should be an error?
|
# positives, we'd need to analyze `nonlocal x` statements in other inner functions.
|
||||||
x: int
|
x: str
|
||||||
def h():
|
def h():
|
||||||
reveal_type(x) # revealed: Unknown | Literal[1]
|
reveal_type(x) # revealed: str
|
||||||
```
|
```
|
||||||
|
|
||||||
## The `nonlocal` keyword
|
## The `nonlocal` keyword
|
||||||
|
@ -229,7 +229,7 @@ def f():
|
||||||
nonlocal x # error: [invalid-syntax] "no binding for nonlocal `x` found"
|
nonlocal x # error: [invalid-syntax] "no binding for nonlocal `x` found"
|
||||||
```
|
```
|
||||||
|
|
||||||
## `nonlocal` bindings respect declared types from the defining scope, even without a binding
|
## Assigning to a `nonlocal` respects the declared type from its defining scope, even without a binding in that scope
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def f():
|
def f():
|
||||||
|
|
|
@ -1618,8 +1618,8 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
// here and just bail out of this loop.
|
// here and just bail out of this loop.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// We found the closest definition. Note that (unlike in `infer_place_load`) this
|
// We found the closest definition. Note that (as in `infer_place_load`) this does
|
||||||
// does *not* need to be a binding. It could be just `x: int`.
|
// *not* need to be a binding. It could be just a declaration, e.g. `x: int`.
|
||||||
nonlocal_use_def_map = self.index.use_def_map(enclosing_scope_file_id);
|
nonlocal_use_def_map = self.index.use_def_map(enclosing_scope_file_id);
|
||||||
declarations = nonlocal_use_def_map.end_of_scope_declarations(enclosing_place_id);
|
declarations = nonlocal_use_def_map.end_of_scope_declarations(enclosing_place_id);
|
||||||
is_local = false;
|
is_local = false;
|
||||||
|
@ -6079,7 +6079,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
let Some(enclosing_place) = enclosing_place_table.place_by_expr(expr) else {
|
let Some(enclosing_place) = enclosing_place_table.place_by_expr(expr) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if enclosing_place.is_bound() {
|
if enclosing_place.is_bound() || enclosing_place.is_declared() {
|
||||||
// We can return early here, because the nearest function-like scope that
|
// We can return early here, because the nearest function-like scope that
|
||||||
// defines a name must be the only source for the nonlocal reference (at
|
// defines a name must be the only source for the nonlocal reference (at
|
||||||
// runtime, it is the scope that creates the cell for our closure.) If the name
|
// runtime, it is the scope that creates the cell for our closure.) If the name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue