mirror of
https://github.com/astral-sh/ruff
synced 2026-01-22 14:00:51 -05:00
Don't treat annotations as resolved in forward references (#5060)
## Summary This behavior dates back to a Pyflakes commit (5fc37cbd), which was used to allow this test to pass: ```py from __future__ import annotations T: object def f(t: T): pass def g(t: 'T'): pass ``` But, I think this is an error. Mypy and Pyright don't accept it -- you can only use variables as type annotations if they're type aliases (i.e., annotated with `TypeAlias`), in which case, there has to be an assignment on the right-hand side (see: [PEP 613](https://peps.python.org/pep-0613/)).
This commit is contained in:
@@ -177,20 +177,22 @@ impl<'a> SemanticModel<'a> {
|
||||
// should prefer it over local resolutions.
|
||||
if self.in_forward_reference() {
|
||||
if let Some(binding_id) = self.scopes.global().get(symbol) {
|
||||
// Mark the binding as used.
|
||||
let context = self.execution_context();
|
||||
let reference_id = self.references.push(ScopeId::global(), range, context);
|
||||
self.bindings[binding_id].references.push(reference_id);
|
||||
|
||||
// Mark any submodule aliases as used.
|
||||
if let Some(binding_id) =
|
||||
self.resolve_submodule(symbol, ScopeId::global(), binding_id)
|
||||
{
|
||||
if !self.bindings[binding_id].kind.is_annotation() {
|
||||
// Mark the binding as used.
|
||||
let context = self.execution_context();
|
||||
let reference_id = self.references.push(ScopeId::global(), range, context);
|
||||
self.bindings[binding_id].references.push(reference_id);
|
||||
}
|
||||
|
||||
return ResolvedRead::Resolved(binding_id);
|
||||
// Mark any submodule aliases as used.
|
||||
if let Some(binding_id) =
|
||||
self.resolve_submodule(symbol, ScopeId::global(), binding_id)
|
||||
{
|
||||
let reference_id = self.references.push(ScopeId::global(), range, context);
|
||||
self.bindings[binding_id].references.push(reference_id);
|
||||
}
|
||||
|
||||
return ResolvedRead::Resolved(binding_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,8 +228,7 @@ impl<'a> SemanticModel<'a> {
|
||||
self.bindings[binding_id].references.push(reference_id);
|
||||
}
|
||||
|
||||
// But if it's a type annotation, don't treat it as resolved, unless we're in a
|
||||
// forward reference. For example, given:
|
||||
// But if it's a type annotation, don't treat it as resolved. For example, given:
|
||||
//
|
||||
// ```python
|
||||
// name: str
|
||||
@@ -236,7 +237,7 @@ impl<'a> SemanticModel<'a> {
|
||||
//
|
||||
// The `name` in `print(name)` should be treated as unresolved, but the `name` in
|
||||
// `name: str` should be treated as used.
|
||||
if !self.in_forward_reference() && self.bindings[binding_id].kind.is_annotation() {
|
||||
if self.bindings[binding_id].kind.is_annotation() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user