Repository: astral-sh/ruff
File: crates/ruff_linter/src/rules/pylint/rules/dict_iter_missing_items.rs (Rust)

Code before:
            };
            (dict_expr, None)
        }
        Stmt::AnnAssign(ann_assign_stmt) => {
            let Some(value) = ann_assign_stmt.value.as_ref() else {
                return false;
            };
            let Expr::Dict(dict_expr) = value.as_ref() else {
                return false;
            };
            (dict_expr, Some(ann_assign_stmt.annotation.as_ref()))
        }
        _ => return false,
    };

    // Check if dict is empty
    let is_empty = dict_expr.iter_keys().next().is_none();

    if is_empty {
        // For empty dicts, check type annotation
        if let Some(annotation) = annotation {
            // Check if annotation is dict[tuple[...], ...] where tuple has 2 elements
            return is_annotation_dict_with_tuple_keys(annotation, semantic);
        }
        // Empty dict without annotation should allow the fix
        return false;
    }

    // For non-empty dicts, check if all keys are 2-tuples
    dict_expr
        .iter_keys()
        .all(|key| matches!(key, Some(Expr::Tuple(tuple)) if tuple.len() == 2))
}

/// Returns true if the annotation is `dict[tuple[T1, T2], ...]` where tuple has exactly 2 elements.
fn is_annotation_dict_with_tuple_keys(annotation: &Expr, semantic: &SemanticModel) -> bool {
    // Handle stringized annotations
    let annotation = if let Expr::StringLiteral(_) = annotation {
        // For stringized annotations, we'd need to parse them, but for now,
        // we'll be conservative and return false (allow the fix)
        return false;
    } else {
        annotation
    };

    // Check if it's a subscript: dict[...]
    let Expr::Subscript(subscript) = annotation else {
        return false;
    };

    // Check if the value is `dict`

Review comment (suggestion):
I think this is all just:

```suggestion
        return annotation.is_some_and(|annotation| is_annotation_dict_with_tuple_keys(annotation, semantic));
```

Code after:
            annotation,
            ..
        }) => (value.as_ref(), Some(annotation.as_ref())),
        _ => return false,
    };

    let Expr::Dict(dict_expr) = value else {
        return false;
    };

    // Check if dict is empty
    let is_empty = dict_expr.is_empty();

    if is_empty {
        // For empty dicts, check type annotation
        return annotation
            .is_some_and(|annotation| is_annotation_dict_with_tuple_keys(annotation, semantic));
    }

    // For non-empty dicts, check if all keys are 2-tuples
    dict_expr
        .iter_keys()
        .all(|key| matches!(key, Some(Expr::Tuple(tuple)) if tuple.len() == 2))
}

/// Returns true if the annotation is `dict[tuple[T1, T2], ...]` where tuple has exactly 2 elements.
fn is_annotation_dict_with_tuple_keys(annotation: &Expr, semantic: &SemanticModel) -> bool {
    // Check if it's a subscript: dict[...]
    let Expr::Subscript(subscript) = annotation else {
        return false;
    };

    // Check if it's dict or typing.Dict
    if !semantic.match_builtin_expr(subscript.value.as_ref(), "dict")
        && !semantic.match_typing_expr(subscript.value.as_ref(), "Dict")
    {
        return false;
    }

    // Extract the slice (should be a tuple: (key_type, value_type))
    let Expr::Tuple(tuple) = subscript.slice.as_ref() else {
        return false;
    };

    // dict[K, V] format - check if K is tuple with 2 elements
    if let [key, _value] = tuple.elts.as_slice() {
        return is_tuple_type_with_two_elements(key, semantic);
    }

    false
}