Repository: astral-sh/ruff
File: crates/ty_python_semantic/src/types/infer/builder/annotation_expression.rs (Rust)

Code before:
                    ) => {
                        let arguments = if let ast::Expr::Tuple(tuple) = slice {
                            &*tuple.elts
                        } else {
                            std::slice::from_ref(slice)
                        };
                        let type_and_qualifiers = if let [argument] = arguments {
                            let mut type_and_qualifiers = self.infer_annotation_expression_impl(
                                argument,
                                PEP613Policy::Disallowed,
                            );

                            // Emit a diagnostic if ClassVar and Final are combined in a class that is
                            // not a dataclass, since Final already implies the semantics of ClassVar.
                            let classvar_and_final =
                                (matches!(type_qualifier, SpecialFormType::Final)
                                    && type_and_qualifiers
                                        .qualifiers
                                        .contains(TypeQualifiers::CLASS_VAR))
                                    || (matches!(type_qualifier, SpecialFormType::ClassVar)
                                        && type_and_qualifiers
                                            .qualifiers
                                            .contains(TypeQualifiers::FINAL));
                            let inside_non_dataclass_class =
                                nearest_enclosing_class(self.db(), self.index, self.scope())
                                    .is_none_or(|class| !class.is_dataclass_like(self.db()));
                            if classvar_and_final && inside_non_dataclass_class {
                                if let Some(builder) = self
                                    .context
                                    .report_lint(&REDUNDANT_FINAL_CLASSVAR, subscript)
                                {
                                    builder.into_diagnostic(format_args!(
                                        "`Combining `ClassVar` and `Final` is redundant"
                                    ));
                                }
                            }

                            match type_qualifier {
                                SpecialFormType::ClassVar => {
                                    type_and_qualifiers.add_qualifier(TypeQualifiers::CLASS_VAR);
                                    if type_and_qualifiers
                                        .inner_type()
                                        .has_non_self_typevar(self.db())
                                        && let Some(builder) =
                                            self.context.report_lint(&INVALID_TYPE_FORM, subscript)
                                    {
                                        builder.into_diagnostic(
                                            "`ClassVar` cannot contain type variables",
                                        );
                                    }
                                }

Review comment (suggestion):
I guess for something like this, the "nearest enclosing class" would be `Some()`:

```py
from dataclasses import dataclass

@dataclass
class F:
    def method(self):
        X: Final[ClassVar[int]] = 42
```

but I guess that would be a separate error anyway, since `ClassVar` is only valid in the class body, so a false negative here probably doesn't matter too much.

Hmm, unrelatedly, should we make this a lazy closure? It's unnecessary work to compute this variable if `classvar_and_final`, already computed above, was `false`

Code after:
                    ) => {
                        let arguments = if let ast::Expr::Tuple(tuple) = slice {
                            &*tuple.elts
                        } else {
                            std::slice::from_ref(slice)
                        };
                        let type_and_qualifiers = if let [argument] = arguments {
                            let mut type_and_qualifiers = self.infer_annotation_expression_impl(
                                argument,
                                PEP613Policy::Disallowed,
                            );

                            // Emit a diagnostic if ClassVar and Final are combined in a class that is
                            // not a dataclass, since Final already implies the semantics of ClassVar.
                            let classvar_and_final = match type_qualifier {
                                SpecialFormType::Final => type_and_qualifiers
                                    .qualifiers
                                    .contains(TypeQualifiers::CLASS_VAR),
                                SpecialFormType::ClassVar => type_and_qualifiers
                                    .qualifiers
                                    .contains(TypeQualifiers::FINAL),
                                _ => false,
                            };
                            if classvar_and_final
                                && nearest_enclosing_class(self.db(), self.index, self.scope())
                                    .is_none_or(|class| !class.is_dataclass_like(self.db()))
                                && let Some(builder) = self
                                    .context
                                    .report_lint(&REDUNDANT_FINAL_CLASSVAR, subscript)
                            {
                                builder.into_diagnostic(format_args!(
                                    "`Combining `ClassVar` and `Final` is redundant"
                                ));
                            }

                            match type_qualifier {
                                SpecialFormType::ClassVar => {
                                    type_and_qualifiers.add_qualifier(TypeQualifiers::CLASS_VAR);
                                    if type_and_qualifiers
                                        .inner_type()
                                        .has_non_self_typevar(self.db())
                                        && let Some(builder) =
                                            self.context.report_lint(&INVALID_TYPE_FORM, subscript)
                                    {
                                        builder.into_diagnostic(
                                            "`ClassVar` cannot contain type variables",
                                        );
                                    }
                                }
                                SpecialFormType::Final => {
                                    type_and_qualifiers.add_qualifier(TypeQualifiers::FINAL);