[ruff] Avoid emitting assignment-in-assert when all references to the assigned variable are themselves inside asserts (RUF018) (#14661)
Some checks are pending
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
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, 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 / 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

This commit is contained in:
Alex Waygood 2024-11-29 13:36:59 +00:00 committed by GitHub
parent b63c2e126b
commit f3d8c023d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 106 additions and 15 deletions

View file

@ -135,6 +135,15 @@ impl<'a> Binding<'a> {
self.flags.contains(BindingFlags::IN_EXCEPT_HANDLER)
}
/// Return `true` if this [`Binding`] took place inside an `assert` statement,
/// e.g. `y` in:
/// ```python
/// assert (y := x**2), y
/// ```
pub const fn in_assert_statement(&self) -> bool {
self.flags.contains(BindingFlags::IN_ASSERT_STATEMENT)
}
/// Return `true` if this [`Binding`] represents a [PEP 613] type alias
/// e.g. `OptString` in:
/// ```python
@ -266,6 +275,15 @@ impl<'a> Binding<'a> {
.map(|statement_id| semantic.statement(statement_id))
}
/// Returns the expression in which the binding was defined
/// (e.g. for the binding `x` in `y = (x := 1)`, return the node representing `x := 1`).
///
/// This is only really applicable for assignment expressions.
pub fn expression<'b>(&self, semantic: &SemanticModel<'b>) -> Option<&'b ast::Expr> {
self.source
.and_then(|expression_id| semantic.parent_expression(expression_id))
}
/// Returns the range of the binding's parent.
pub fn parent_range(&self, semantic: &SemanticModel) -> Option<TextRange> {
self.statement(semantic).and_then(|parent| {
@ -406,6 +424,14 @@ bitflags! {
/// [PEP 695]: https://peps.python.org/pep-0695/#generic-type-alias
const DEFERRED_TYPE_ALIAS = 1 << 12;
/// The binding took place inside an `assert` statement
///
/// For example, `x` in the following snippet:
/// ```python
/// assert (x := y**2) > 42, x
/// ```
const IN_ASSERT_STATEMENT = 1 << 13;
/// The binding represents any type alias.
const TYPE_ALIAS = Self::ANNOTATED_TYPE_ALIAS.bits() | Self::DEFERRED_TYPE_ALIAS.bits();
}

View file

@ -1839,6 +1839,11 @@ impl<'a> SemanticModel<'a> {
self.flags.intersects(SemanticModelFlags::EXCEPTION_HANDLER)
}
/// Return `true` if the model is in an `assert` statement.
pub const fn in_assert_statement(&self) -> bool {
self.flags.intersects(SemanticModelFlags::ASSERT_STATEMENT)
}
/// Return `true` if the model is in an f-string.
pub const fn in_f_string(&self) -> bool {
self.flags.intersects(SemanticModelFlags::F_STRING)
@ -2432,6 +2437,14 @@ bitflags! {
/// [PEP 695]: https://peps.python.org/pep-0695/#generic-type-alias
const DEFERRED_TYPE_ALIAS = 1 << 28;
/// The model is visiting an `assert` statement.
///
/// For example, the model might be visiting `y` in
/// ```python
/// assert (y := x**2) > 42, y
/// ```
const ASSERT_STATEMENT = 1 << 29;
/// The context is in any type annotation.
const ANNOTATION = Self::TYPING_ONLY_ANNOTATION.bits() | Self::RUNTIME_EVALUATED_ANNOTATION.bits() | Self::RUNTIME_REQUIRED_ANNOTATION.bits();

View file

@ -93,6 +93,11 @@ impl ResolvedReference {
self.flags
.intersects(SemanticModelFlags::ANNOTATED_TYPE_ALIAS)
}
/// Return `true` if the context is inside an `assert` statement
pub const fn in_assert_statement(&self) -> bool {
self.flags.intersects(SemanticModelFlags::ASSERT_STATEMENT)
}
}
impl Ranged for ResolvedReference {