mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 12:29:48 +00:00
[ruff
] Avoid false positives for RUF027 for typing context bindings. (#15037)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Closes #14000 ## Summary For typing context bindings we know that they won't be available at runtime. We shouldn't recommend a fix, that will result in name errors at runtime. ## Test Plan `cargo nextest run`
This commit is contained in:
parent
e8e461da6a
commit
c0b7c36d43
3 changed files with 49 additions and 5 deletions
|
@ -68,3 +68,9 @@ def negative_cases():
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
async def read_item(item_id):
|
async def read_item(item_id):
|
||||||
return {"item_id": item_id}
|
return {"item_id": item_id}
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
t = "foo/{date}"
|
||||||
|
|
|
@ -209,7 +209,14 @@ fn should_be_fstring(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if semantic
|
if semantic
|
||||||
.lookup_symbol(id)
|
// the parsed expression nodes have incorrect ranges
|
||||||
|
// so we need to use the range of the literal for the
|
||||||
|
// lookup in order to get reasonable results.
|
||||||
|
.simulate_runtime_load_at_location_in_scope(
|
||||||
|
id,
|
||||||
|
literal.range(),
|
||||||
|
semantic.scope_id,
|
||||||
|
)
|
||||||
.map_or(true, |id| semantic.binding(id).kind.is_builtin())
|
.map_or(true, |id| semantic.binding(id).kind.is_builtin())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -711,12 +711,43 @@ impl<'a> SemanticModel<'a> {
|
||||||
/// References from within an [`ast::Comprehension`] can produce incorrect
|
/// References from within an [`ast::Comprehension`] can produce incorrect
|
||||||
/// results when referring to a [`BindingKind::NamedExprAssignment`].
|
/// results when referring to a [`BindingKind::NamedExprAssignment`].
|
||||||
pub fn simulate_runtime_load(&self, name: &ast::ExprName) -> Option<BindingId> {
|
pub fn simulate_runtime_load(&self, name: &ast::ExprName) -> Option<BindingId> {
|
||||||
let symbol = name.id.as_str();
|
self.simulate_runtime_load_at_location_in_scope(name.id.as_str(), name.range, self.scope_id)
|
||||||
let range = name.range;
|
}
|
||||||
|
|
||||||
|
/// Simulates a runtime load of the given symbol.
|
||||||
|
///
|
||||||
|
/// This should not be run until after all the bindings have been visited.
|
||||||
|
///
|
||||||
|
/// The main purpose of this method and what makes this different from
|
||||||
|
/// [`SemanticModel::lookup_symbol_in_scope`] is that it may be used to
|
||||||
|
/// perform speculative name lookups.
|
||||||
|
///
|
||||||
|
/// In most cases a load can be accurately modeled simply by calling
|
||||||
|
/// [`SemanticModel::lookup_symbol`] at the right time during semantic
|
||||||
|
/// analysis, however for speculative lookups this is not the case,
|
||||||
|
/// since we're aiming to change the semantic meaning of our load.
|
||||||
|
/// E.g. we want to check what would happen if we changed a forward
|
||||||
|
/// reference to an immediate load or vice versa.
|
||||||
|
///
|
||||||
|
/// Use caution when utilizing this method, since it was primarily designed
|
||||||
|
/// to work for speculative lookups from within type definitions, which
|
||||||
|
/// happen to share some nice properties, where attaching each binding
|
||||||
|
/// to a range in the source code and ordering those bindings based on
|
||||||
|
/// that range is a good enough approximation of which bindings are
|
||||||
|
/// available at runtime for which reference.
|
||||||
|
///
|
||||||
|
/// References from within an [`ast::Comprehension`] can produce incorrect
|
||||||
|
/// results when referring to a [`BindingKind::NamedExprAssignment`].
|
||||||
|
pub fn simulate_runtime_load_at_location_in_scope(
|
||||||
|
&self,
|
||||||
|
symbol: &str,
|
||||||
|
symbol_range: TextRange,
|
||||||
|
scope_id: ScopeId,
|
||||||
|
) -> Option<BindingId> {
|
||||||
let mut seen_function = false;
|
let mut seen_function = false;
|
||||||
let mut class_variables_visible = true;
|
let mut class_variables_visible = true;
|
||||||
let mut source_order_sensitive_lookup = true;
|
let mut source_order_sensitive_lookup = true;
|
||||||
for (index, scope_id) in self.scopes.ancestor_ids(self.scope_id).enumerate() {
|
for (index, scope_id) in self.scopes.ancestor_ids(scope_id).enumerate() {
|
||||||
let scope = &self.scopes[scope_id];
|
let scope = &self.scopes[scope_id];
|
||||||
|
|
||||||
// Only once we leave a function scope and its enclosing type scope should
|
// Only once we leave a function scope and its enclosing type scope should
|
||||||
|
@ -776,7 +807,7 @@ impl<'a> SemanticModel<'a> {
|
||||||
_ => binding.range,
|
_ => binding.range,
|
||||||
};
|
};
|
||||||
|
|
||||||
if binding_range.ordering(range).is_lt() {
|
if binding_range.ordering(symbol_range).is_lt() {
|
||||||
return Some(shadowed_id);
|
return Some(shadowed_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue