mirror of https://github.com/astral-sh/ruff
[`pylint`] - restrict `iteration-over-set` to only work on sets of literals (`PLC0208`) (#13731)
This commit is contained in:
parent
c2dc502f3b
commit
f3612c2717
|
|
@ -50,3 +50,13 @@ for number in {i for i in range(10)}: # set comprehensions are fine
|
||||||
|
|
||||||
for item in {*numbers_set, 4, 5, 6}: # set unpacking is fine
|
for item in {*numbers_set, 4, 5, 6}: # set unpacking is fine
|
||||||
print(f"I like {item}.")
|
print(f"I like {item}.")
|
||||||
|
|
||||||
|
for item in {1, 2, 3, 4, 5, 6, 2 // 1}: # operations in set literals are fine
|
||||||
|
print(f"I like {item}.")
|
||||||
|
|
||||||
|
for item in {1, 2, 3, 4, 5, 6, int("7")}: # calls in set literals are fine
|
||||||
|
print(f"I like {item}.")
|
||||||
|
|
||||||
|
for item in {1, 2, 2}: # duplicate literals will be ignored
|
||||||
|
# B033 catches this
|
||||||
|
print(f"I like {item}.")
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::Expr;
|
use ruff_python_ast::{comparable::ComparableExpr, Expr};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for iterations over `set` literals.
|
/// Checks for iteration over a `set` literal where each element in the set is
|
||||||
|
/// itself a literal value.
|
||||||
///
|
///
|
||||||
/// ## Why is this bad?
|
/// ## Why is this bad?
|
||||||
/// Iterating over a `set` is less efficient than iterating over a sequence
|
/// Iterating over a `set` is less efficient than iterating over a sequence
|
||||||
|
|
@ -46,10 +48,20 @@ pub(crate) fn iteration_over_set(checker: &mut Checker, expr: &Expr) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if set.iter().any(Expr::is_starred_expr) {
|
if set.iter().any(|value| !value.is_literal_expr()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut seen_values = FxHashSet::with_capacity_and_hasher(set.len(), FxBuildHasher);
|
||||||
|
for value in set {
|
||||||
|
let comparable_value = ComparableExpr::from(value);
|
||||||
|
if !seen_values.insert(comparable_value) {
|
||||||
|
// if the set contains a duplicate literal value, early exit.
|
||||||
|
// rule `B033` can catch that.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut diagnostic = Diagnostic::new(IterationOverSet, expr.range());
|
let mut diagnostic = Diagnostic::new(IterationOverSet, expr.range());
|
||||||
|
|
||||||
let tuple = if let [elt] = set.elts.as_slice() {
|
let tuple = if let [elt] = set.elts.as_slice() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue