Repository: astral-sh/ruff
File: crates/ruff_linter/src/checkers/ast/analyze/deferred_comprehensions.rs (Rust)

Code before:

use crate::checkers::ast::Checker;
use crate::codes::Rule;
use crate::rules::perflint;

/// Run lint rules over all deferred comprehensions in the [`SemanticModel`].
pub(crate) fn deferred_comprehensions(checker: &mut Checker) {
    while !checker.analyze.comprehensions.is_empty() {
        let comprehensions = std::mem::take(&mut checker.analyze.comprehensions);
        for snapshot in comprehensions {
            checker.semantic.restore(snapshot);

            let Some(generators) =
                checker
                    .semantic
                    .current_expression()
                    .and_then(|expr| match expr {
                        Expr::ListComp(comp) => Some(comp.generators.as_slice()),
                        Expr::SetComp(comp) => Some(comp.generators.as_slice()),
                        Expr::DictComp(comp) => Some(comp.generators.as_slice()),
                        Expr::Generator(generator) => Some(generator.generators.as_slice()),
                        _ => None,
                    })
            else {
                continue;
            };

            for generator in generators {
                if checker.is_rule_enabled(Rule::IncorrectDictIterator) {
                    perflint::rules::incorrect_dict_iterator_comprehension(checker, generator);
                }
            }
        }
    }
}


Review comment (bug):
We may want to include a `debug_assert!` here at least. The other deferred checks actually use `unreachable!`:

https://github.com/astral-sh/ruff/blob/313336b61bba043a636084e6047eccaea9a4e773/crates/ruff_linter/src/checkers/ast/analyze/deferred_for_loops.rs#L14-L16


```suggestion
                debug_assert!(false, "Expected a comprehension");
                continue;
```

Code after:

use crate::checkers::ast::Checker;
use crate::codes::Rule;
use crate::rules::perflint;

/// Run lint rules over all deferred comprehensions in the [`SemanticModel`].
pub(crate) fn deferred_comprehensions(checker: &mut Checker) {
    while !checker.analyze.comprehensions.is_empty() {
        let comprehensions = std::mem::take(&mut checker.analyze.comprehensions);
        for snapshot in comprehensions {
            checker.semantic.restore(snapshot);

            let Some(generators) =
                checker
                    .semantic
                    .current_expression()
                    .and_then(|expr| match expr {
                        Expr::ListComp(comp) => Some(comp.generators.as_slice()),
                        Expr::SetComp(comp) => Some(comp.generators.as_slice()),
                        Expr::DictComp(comp) => Some(comp.generators.as_slice()),
                        Expr::Generator(generator) => Some(generator.generators.as_slice()),
                        _ => None,
                    })
            else {
                debug_assert!(false, "Expected a comprehension");
                continue;
            };

            for generator in generators {
                if checker.is_rule_enabled(Rule::IncorrectDictIterator) {
                    perflint::rules::incorrect_dict_iterator_comprehension(checker, generator);
                }
            }
        }
    }
}