use itertools::Either;
use ruff_python_ast::helpers::is_dotted_name;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, PythonVersion};
use ruff_text_size::Ranged;

use super::{DeferredExpressionState, TypeInferenceBuilder};
use crate::types::call::CallArguments;
use crate::types::diagnostic::{
    self, EXPERIMENTAL_SYNTAX, INVALID_TYPE_FORM, NOT_SUBSCRIPTABLE, UNBOUND_TYPE_VARIABLE,
    UNSUPPORTED_OPERATOR, report_invalid_argument_number_to_special_form,
    report_invalid_arguments_to_callable, report_invalid_concatenate_last_arg,
    report_missing_type_arguments, report_unsupported_binary_operation,
};
use crate::types::infer::builder::subscript::AnnotatedExprContext;
use crate::types::infer::{InferenceFlags, TypeExpressionFlags};
use crate::types::signatures::{ConcatenateTail, Signature};
use crate::types::special_form::{AliasSpec, LegacyStdlibAlias};
use crate::types::string_annotation::parse_string_annotation;
use crate::types::tuple::{TupleSpecBuilder, TupleType};
use ty_python_core::scope::ScopeKind;

use crate::types::{
    BindingContext, CallableType, DynamicType, GenericContext, IntersectionBuilder,
    IntersectionType, KnownClass, KnownInstanceType, LintDiagnosticGuard, LiteralValueTypeKind,
    Parameter, Parameters, SpecialFormType, SubclassOfType, Type, TypeAliasType, TypeContext,
    TypeFormType, TypeGuardType, TypeIsType, TypeMapping, TypeVarKind, UnionBuilder, UnionType,
    any_over_type, todo_type,
};
use crate::{FxOrderSet, Program, add_inferred_python_version_hint_to_diagnostic};

/// Type expressions
impl<'db> TypeInferenceBuilder<'db, '_> {
    pub(super) const fn type_expression_context(&self) -> &'static str {
        self.inference_flags().type_expression_context()
    }

    /// Infer the type of a type expression.
    pub(super) fn infer_type_expression(&mut self, expression: &ast::Expr) -> Type<'db> {
        let previous_deferred_state = self.deferred_state;
        let was_in_type_expression = self
            .inference_flags()
            .contains(InferenceFlags::IN_TYPE_EXPRESSION);
        let was_in_nested_type_expression = self
            .inference_flags()
            .contains(InferenceFlags::IN_NESTED_TYPE_EXPRESSION);
        let previously_in_nested_type_expression = self.context.inference_flags.replace(
            InferenceFlags::IN_NESTED_TYPE_EXPRESSION,
            was_in_type_expression || was_in_nested_type_expression,
        );
        let previously_in_type_expression = self
            .context
            .inference_flags
            .replace(InferenceFlags::IN_TYPE_EXPRESSION, true);

        // `DeferredExpressionState::InStringAnnotation` takes precedence over other states.
        // However, if it's not a stringified annotation, we must still ensure that annotation expressions
        // are always deferred in stub files.
        match previous_deferred_state {
            DeferredExpressionState::None => {
                if self.in_stub() {
                    self.deferred_state = DeferredExpressionState::Deferred;
                }
            }
            DeferredExpressionState::InStringAnnotation(_) | DeferredExpressionState::Deferred => {}
        }

        let ty = self.infer_type_expression_no_store(expression);
        self.deferred_state = previous_deferred_state;
        self.context.inference_flags.set(
            InferenceFlags::IN_NESTED_TYPE_EXPRESSION,
            previously_in_nested_type_expression,
        );
        self.context.inference_flags.set(
            InferenceFlags::IN_TYPE_EXPRESSION,
            previously_in_type_expression,
        );
        self.store_expression_type(expression, ty);
        ty
    }

    /// Similar to [`infer_type_expression`], but accepts a [`DeferredExpressionState`].
    ///
    /// [`infer_type_expression`]: TypeInferenceBuilder::infer_type_expression
    pub(super) fn infer_type_expression_with_state(
        &mut self,
        expression: &ast::Expr,
        deferred_state: DeferredExpressionState,
    ) -> Type<'db> {
        let previous_deferred_state = std::mem::replace(&mut self.deferred_state, deferred_state);
        let annotation_ty = self.infer_type_expression(expression);
        self.deferred_state = previous_deferred_state;
        annotation_ty
    }

    fn report_invalid_type_expression(
        &self,
        expression: impl Ranged,
        message: impl std::fmt::Display,
    ) -> Option<LintDiagnosticGuard<'_, '_>> {
        self.context
            .report_lint(&INVALID_TYPE_FORM, expression)
            .map(|builder| {
                diagnostic::add_type_expression_reference_link(builder.into_diagnostic(message))
            })
    }

    pub(super) fn infer_name_or_attribute_type_expression(
        &self,
        ty: Type<'db>,
        annotation: &ast::Expr,
    ) -> Type<'db> {
        if annotation.is_attribute_expr()
            && let Type::TypeVar(tvar) = ty
            && tvar.paramspec_attr(self.db()).is_some()
        {
            return ty;
        }
        report_missing_type_arguments(&self.context, ty, annotation);
        let result_ty = ty
            .default_specialize(self.db())
            .in_type_expression(
                self.db(),
                self.scope(),
                self.typevar_binding_context,
                self.inference_flags(),
            )
            .unwrap_or_else(|error| {
                error.into_fallback_type(&self.context, annotation, self.inference_flags())
            });
        self.check_for_unbound_type_variable(annotation, result_ty)
    }

    /// Infer the type of a type expression without storing the result.
    pub(super) fn infer_type_expression_no_store(&mut self, expression: &ast::Expr) -> Type<'db> {
        let ignore_runtime_errors = |builder: &Self| {
            builder.deferred_state.is_deferred()
                || builder.in_stub()
                || builder.is_in_type_checking_block(builder.scope(), expression)
                || builder
                    .inference_flags()
                    .contains(InferenceFlags::IN_PEP_613_ALIAS_FIRST_PASS)
        };

        // https://typing.python.org/en/latest/spec/annotations.html#grammar-token-expression-grammar-type_expression
        match expression {
            ast::Expr::Name(name) => match name.ctx {
                ast::ExprContext::Load => {
                    let ty = self.infer_name_expression(name);
                    self.infer_name_or_attribute_type_expression(ty, expression)
                }
                ast::ExprContext::Invalid => Type::unknown(),
                ast::ExprContext::Store | ast::ExprContext::Del => {
                    todo_type!("Name expression annotation in Store/Del context")
                }
            },

            ast::Expr::Attribute(attribute_expression) => {
                if is_dotted_name(expression) {
                    match attribute_expression.ctx {
                        ast::ExprContext::Load => {
                            let ty = self.infer_attribute_expression(attribute_expression);
                            self.infer_name_or_attribute_type_expression(ty, expression)
                        }
                        ast::ExprContext::Invalid => Type::unknown(),
                        ast::ExprContext::Store | ast::ExprContext::Del => {
                            todo_type!("Attribute expression annotation in Store/Del context")
                        }
                    }
                } else {
                    if !self.in_string_annotation() {
                        self.infer_attribute_expression(attribute_expression);
                    }
                    self.report_invalid_type_expression(
                        expression,
                        format_args!(
                            "Only simple names, dotted names and subscripts \
                            can be used in {}s",
                            self.type_expression_context()
                        ),
                    );
                    Type::unknown()
                }
            }

            ast::Expr::NoneLiteral(_literal) => Type::none(self.db()),

            // https://typing.python.org/en/latest/spec/annotations.html#string-annotations
            ast::Expr::StringLiteral(string) => self.infer_string_type_expression(string),

            ast::Expr::Subscript(subscript) => {
                let ast::ExprSubscript {
                    value,
                    slice,
                    ctx: _,
                    range: _,
                    node_index: _,
                } = subscript;

                let value_ty = self.infer_expression(value, TypeContext::default());

                if is_dotted_name(value) {
                    // Preserve the flag for another `Unpack` so that nested unpacking emits a
                    // diagnostic. Other subscripts are no longer the direct unpack operand.
                    let previously_in_unpack_type_argument =
                        if value_ty == Type::SpecialForm(SpecialFormType::Unpack) {
                            None
                        } else {
                            Some(
                                self.context
                                    .inference_flags
                                    .replace(InferenceFlags::IN_UNPACK_TYPE_ARGUMENT, false),
                            )
                        };
                    let ty =
                        self.infer_subscript_type_expression_no_store(subscript, slice, value_ty);
                    if let Some(previously_in_unpack_type_argument) =
                        previously_in_unpack_type_argument
                    {
                        self.context.inference_flags.set(
                            InferenceFlags::IN_UNPACK_TYPE_ARGUMENT,
                            previously_in_unpack_type_argument,
                        );
                    }
                    ty
                } else {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    self.report_invalid_type_expression(
                        expression,
                        format_args!(
                            "Only simple names and dotted names can be subscripted in {}s",
                            self.type_expression_context()
                        ),
                    );
                    Type::unknown()
                }
            }

            ast::Expr::BinOp(binary) => {
                match binary.op {
                    // PEP-604 unions are okay, e.g., `int | str`
                    ast::Operator::BitOr => {
                        let left_ty = self.infer_type_expression(&binary.left);
                        let right_ty = self.infer_type_expression(&binary.right);

                        // Detect runtime errors from e.g. `int | "bytes"` on Python <3.14 without `__future__` annotations.
                        if !ignore_runtime_errors(self) {
                            let mut speculative_builder = self.speculate_without_diagnostics();
                            // If the left-hand side of the union is itself a PEP-604 union,
                            // we'll already have checked whether it can be used with `|` in a previous inference step
                            // and emitted a diagnostic if it was appropriate. We should skip inferring it here to
                            // avoid duplicate diagnostics; just assume that the l.h.s. is a `UnionType` instance
                            // in that case.
                            let left_type_value = speculative_builder
                                .infer_expression(&binary.left, TypeContext::default());
                            let right_type_value = speculative_builder
                                .infer_expression(&binary.right, TypeContext::default());

                            let dunder_fails = Type::try_call_bin_op(
                                self.db(),
                                left_type_value,
                                ast::Operator::BitOr,
                                right_type_value,
                            )
                            .is_err();

                            // As well as trying the normal dunder lookup,
                            // we also check for the case where one of the operands is a class-literal type
                            // or generic-alias type and the other is a string literal. The normal dunder lookup
                            // fails to catch this error, since typeshed annotates `type.__(r)or__` as accepting `Any`.
                            let should_emit_error = if dunder_fails {
                                true
                            } else {
                                let literal = match (left_type_value, right_type_value) {
                                    (Type::ClassLiteral(class), Type::LiteralValue(literal))
                                    | (Type::LiteralValue(literal), Type::ClassLiteral(class))
                                        if class.metaclass(self.db())
                                            == KnownClass::Type.to_class_literal(self.db()) =>
                                    {
                                        Some(literal)
                                    }
                                    (Type::GenericAlias(_), Type::LiteralValue(literal))
                                    | (Type::LiteralValue(literal), Type::GenericAlias(_)) => {
                                        Some(literal)
                                    }
                                    _ => None,
                                };
                                literal.is_some_and(|literal| !literal.is_enum())
                            };

                            if should_emit_error
                                && let Some(builder) =
                                    self.context.report_lint(&UNSUPPORTED_OPERATOR, binary)
                            {
                                let mut diagnostic =
                                    builder.into_diagnostic("Unsupported `|` operation");

                                if left_type_value.is_equivalent_to(self.db(), right_type_value) {
                                    diagnostic.set_primary_message(format_args!(
                                        "Both operands have type `{}`",
                                        left_type_value.display(self.db())
                                    ));
                                    diagnostic.set_concise_message(format_args!(
                                        "Operator `|` is unsupported between \
                                        two objects of type `{}`",
                                        left_type_value.display(self.db())
                                    ));
                                } else {
                                    for (operand, ty) in [
                                        (&*binary.left, left_type_value),
                                        (&*binary.right, right_type_value),
                                    ] {
                                        diagnostic.annotate(
                                            self.context.secondary(operand).message(format_args!(
                                                "Has type `{}`",
                                                ty.display(self.db())
                                            )),
                                        );
                                    }
                                    diagnostic.set_concise_message(format_args!(
                                        "Operator `|` is unsupported between \
                                        objects of type `{}` and `{}`",
                                        left_type_value.display(self.db()),
                                        right_type_value.display(self.db())
                                    ));
                                }

                                match self.scope.scope(self.db()).kind() {
                                    ScopeKind::TypeAlias => diagnostic.info(
                                        "A type alias scope is lazy but will be \
                                        executed at runtime if the `__value__` property is \
                                        accessed",
                                    ),
                                    ScopeKind::TypeParams => diagnostic.info(
                                        "Type parameter scopes are lazy but may be \
                                        executed at runtime if the `__bound__`, `__value__`
                                        or `__constraints__` property of a type parameter is \
                                        accessed",
                                    ),
                                    _ => {
                                        let python_version =
                                            Program::get(self.db()).python_version(self.db());

                                        if python_version < PythonVersion::PY314 {
                                            diagnostic.info(format_args!(
                                                "All {}s are evaluated at \
                                                runtime by default on Python <3.14",
                                                self.type_expression_context()
                                            ));
                                            add_inferred_python_version_hint_to_diagnostic(
                                                self.db(),
                                                &mut diagnostic,
                                                "inferring types",
                                            );
                                            if binary.left.is_string_literal_expr()
                                                || binary.right.is_string_literal_expr()
                                            {
                                                diagnostic.help(
                                                    "Put quotes around the whole union \
                                                    rather than just certain elements",
                                                );
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        UnionType::from_elements_leave_aliases(self.db(), [left_ty, right_ty])
                    }
                    ast::Operator::BitAnd => {
                        if let Some(builder) =
                            self.context.report_lint(&EXPERIMENTAL_SYNTAX, binary)
                        {
                            builder.into_diagnostic("Intersection type syntax is experimental");
                        }

                        let left_ty = self.infer_type_expression(&binary.left);
                        let right_ty = self.infer_type_expression(&binary.right);

                        if !ignore_runtime_errors(self) {
                            // Infer the operands as values to report the types used by the runtime
                            // operation rather than their interpretation as type expressions.
                            let mut speculative_builder = self.speculate_without_diagnostics();
                            let left_value = speculative_builder
                                .infer_expression(&binary.left, TypeContext::default());
                            let right_value = speculative_builder
                                .infer_expression(&binary.right, TypeContext::default());
                            if Type::try_call_bin_op(
                                self.db(),
                                left_value,
                                ast::Operator::BitAnd,
                                right_value,
                            )
                            .is_err()
                            {
                                report_unsupported_binary_operation(
                                    &self.context,
                                    binary,
                                    left_value,
                                    right_value,
                                    ast::Operator::BitAnd,
                                );
                            }
                        }

                        IntersectionType::from_two_elements(self.db(), left_ty, right_ty)
                    }
                    // anything else is an invalid annotation:
                    op => {
                        // Avoid inferring the types of invalid binary expressions that have been
                        // parsed from a string annotation, as they are not present in the semantic
                        // index.
                        if !self.in_string_annotation() {
                            self.infer_binary_expression(binary, TypeContext::default());
                        }
                        self.report_invalid_type_expression(
                            expression,
                            format_args!(
                                "Invalid binary operator `{}` in type annotation",
                                op.as_str()
                            ),
                        );
                        Type::unknown()
                    }
                }
            }

            // =====================================================================================
            // Forms which are invalid in the context of annotation expressions: we infer their
            // nested expressions as normal expressions, but the type of the top-level expression is
            // always `Type::unknown` in these cases.
            // =====================================================================================
            ast::Expr::BytesLiteral(bytes) => {
                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Bytes literals are not allowed in this context in a {}",
                        self.type_expression_context()
                    ),
                ) {
                    if let Some(single_element) = bytes.as_single_part_bytestring()
                        && let Ok(valid_string) = String::from_utf8(single_element.value.to_vec())
                    {
                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `typing.Literal[b\"{valid_string}\"]`?"
                        ));
                    }
                }
                Type::unknown()
            }

            ast::Expr::NumberLiteral(ast::ExprNumberLiteral {
                value: ast::Number::Int(int),
                ..
            }) => {
                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Int literals are not allowed in this context in a {}",
                        self.type_expression_context()
                    ),
                ) {
                    if let Some(int) = int.as_i64() {
                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `typing.Literal[{int}]`?"
                        ));
                    }
                }

                Type::unknown()
            }

            ast::Expr::NumberLiteral(ast::ExprNumberLiteral {
                value: ast::Number::Float(_),
                ..
            }) => {
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Float literals are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::NumberLiteral(ast::ExprNumberLiteral {
                value: ast::Number::Complex { .. },
                ..
            }) => {
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Complex literals are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::BooleanLiteral(bool_value) => {
                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Boolean literals are not allowed in this context in a {}",
                        self.type_expression_context()
                    ),
                ) {
                    diagnostic.set_primary_message(format_args!(
                        "Did you mean `typing.Literal[{}]`?",
                        if bool_value.value { "True" } else { "False" }
                    ));
                }
                Type::unknown()
            }

            ast::Expr::List(list) => {
                let db = self.db();

                if !self.in_string_annotation() {
                    self.infer_list_expression(list, TypeContext::default());
                }

                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "List literals are not allowed in this context in a {}",
                        self.type_expression_context()
                    ),
                ) && let [single_element] = &*list.elts
                {
                    let mut speculative_builder = self.speculate_without_diagnostics();
                    let inner_type = speculative_builder.infer_type_expression(single_element);

                    if inner_type.is_hintable(self.db()) {
                        let hinted_type =
                            KnownClass::List.to_specialized_instance(db, &[inner_type]);

                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `{}`?",
                            hinted_type.display(self.db()),
                        ));
                    }
                }
                Type::unknown()
            }

            ast::Expr::Tuple(tuple) => {
                if tuple.parenthesized {
                    if !self.in_string_annotation() {
                        for element in tuple {
                            self.infer_expression(element, TypeContext::default());
                        }
                    }

                    if let Some(mut diagnostic) = self.report_invalid_type_expression(
                        expression,
                        format_args!(
                            "Tuple literals are not allowed in this context in a {}",
                            self.type_expression_context()
                        ),
                    ) {
                        let mut speculative = self.speculate_without_diagnostics();
                        let inner_types: Vec<Type<'db>> = tuple
                            .elts
                            .iter()
                            .map(|element| speculative.infer_type_expression(element))
                            .collect();

                        if inner_types.iter().all(|ty| ty.is_hintable(self.db())) {
                            let hinted_type = Type::heterogeneous_tuple(self.db(), inner_types);
                            diagnostic.set_primary_message(format_args!(
                                "Did you mean `{}`?",
                                hinted_type.display(self.db()),
                            ));
                        }
                    }
                } else {
                    for element in tuple {
                        self.infer_type_expression(element);
                    }
                }

                Type::unknown()
            }

            ast::Expr::BoolOp(bool_op) => {
                if !self.in_string_annotation() {
                    self.infer_boolean_expression(bool_op, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Boolean operations are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Named(named) => {
                if !self.in_string_annotation() {
                    self.infer_named_expression(named);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Named expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::UnaryOp(
                unary @ ast::ExprUnaryOp {
                    op: ast::UnaryOp::Invert,
                    operand,
                    ..
                },
            ) => {
                if let Some(builder) = self.context.report_lint(&EXPERIMENTAL_SYNTAX, unary) {
                    builder.into_diagnostic("Negation type syntax is experimental");
                }

                let operand_ty = self.infer_type_expression(operand);

                if !ignore_runtime_errors(self) {
                    let operand_value = self
                        .speculate_without_diagnostics()
                        .infer_expression(operand, TypeContext::default());
                    if let Err(error) = operand_value.try_call_dunder(
                        self.db(),
                        "__invert__",
                        CallArguments::none(),
                        TypeContext::default(),
                    ) {
                        self.report_unsupported_unary_operator(
                            unary,
                            ast::UnaryOp::Invert,
                            operand_value,
                            "__invert__",
                            Some(&error),
                        );
                    }
                }

                operand_ty.negate(self.db())
            }

            ast::Expr::UnaryOp(unary) => {
                if !self.in_string_annotation() {
                    self.infer_unary_expression(unary);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Unary operations are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Lambda(lambda_expression) => {
                if !self.in_string_annotation() {
                    self.infer_lambda_expression(lambda_expression, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`lambda` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::If(if_expression) => {
                if !self.in_string_annotation() {
                    self.infer_if_expression(if_expression, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`if` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Dict(dict) => {
                if !self.in_string_annotation() {
                    self.infer_dict_expression(dict, TypeContext::default());
                }
                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Dict literals are not allowed in {}s",
                        self.type_expression_context()
                    ),
                ) && let [
                    ast::DictItem {
                        key: Some(key),
                        value,
                    },
                ] = &*dict.items
                {
                    let mut speculative = self.speculate_without_diagnostics();
                    let key_type = speculative.infer_type_expression(key);
                    let value_type = speculative.infer_type_expression(value);
                    if key_type.is_hintable(self.db()) && value_type.is_hintable(self.db()) {
                        let hinted_type = KnownClass::Dict
                            .to_specialized_instance(self.db(), &[key_type, value_type]);
                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `{}`?",
                            hinted_type.display(self.db()),
                        ));
                    }
                }
                Type::unknown()
            }

            ast::Expr::Set(set) => {
                if !self.in_string_annotation() {
                    self.infer_set_expression(set, TypeContext::default());
                }
                if let Some(mut diagnostic) = self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Set literals are not allowed in {}s",
                        self.type_expression_context()
                    ),
                ) && let [single_element] = &*set.elts
                {
                    let mut speculative_builder = self.speculate_without_diagnostics();
                    let inner_type = speculative_builder.infer_type_expression(single_element);

                    if inner_type.is_hintable(self.db()) {
                        let hinted_type =
                            KnownClass::Set.to_specialized_instance(self.db(), &[inner_type]);

                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `{}`?",
                            hinted_type.display(self.db()),
                        ));
                    }
                }
                Type::unknown()
            }

            ast::Expr::DictComp(dictcomp) => {
                if !self.in_string_annotation() {
                    self.infer_dict_comprehension_expression(dictcomp, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Dict comprehensions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::ListComp(listcomp) => {
                if !self.in_string_annotation() {
                    self.infer_list_comprehension_expression(listcomp, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "List comprehensions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::SetComp(setcomp) => {
                if !self.in_string_annotation() {
                    self.infer_set_comprehension_expression(setcomp, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Set comprehensions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Generator(generator) => {
                if !self.in_string_annotation() {
                    self.infer_generator_expression(generator, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Generator expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Await(await_expression) => {
                if !self.in_string_annotation() {
                    self.infer_await_expression(await_expression, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`await` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Yield(yield_expression) => {
                if !self.in_string_annotation() {
                    self.infer_yield_expression(yield_expression);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`yield` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::YieldFrom(yield_from) => {
                if !self.in_string_annotation() {
                    self.infer_yield_from_expression(yield_from);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`yield from` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Compare(compare) => {
                if !self.in_string_annotation() {
                    self.infer_compare_expression(compare);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Comparison expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Call(call_expr) => {
                if !self.in_string_annotation() {
                    self.infer_call_expression(call_expr, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Function calls are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::FString(fstring) => {
                if !self.in_string_annotation() {
                    self.infer_fstring_expression(fstring);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "F-strings are not allowed in {}s",
                        self.type_expression_context(),
                    ),
                );
                Type::unknown()
            }

            ast::Expr::TString(tstring) => {
                if !self.in_string_annotation() {
                    self.infer_tstring_expression(tstring);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "T-strings are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Slice(slice) => {
                if !self.in_string_annotation() {
                    self.infer_slice_expression(slice);
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Slices are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            // =================================================================================
            // Branches where we probably should emit diagnostics in some context, but don't yet
            // =================================================================================
            // TODO: When this case is implemented and the `todo!` usage
            // is removed, consider adding `todo = "warn"` to the Clippy
            // lint configuration in `Cargo.toml`. At time of writing,
            // 2025-08-22, this was the only usage of `todo!` in ruff/ty.
            // ---AG
            ast::Expr::IpyEscapeCommand(_) => todo!("Implement Ipy escape command support"),

            ast::Expr::EllipsisLiteral(_) => {
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`...` is not allowed in this context in a {}",
                        self.type_expression_context(),
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Starred(starred) => self.infer_starred_type_expression(starred),
        }
    }

    fn infer_starred_type_expression(&mut self, starred: &ast::ExprStarred) -> Type<'db> {
        let ast::ExprStarred {
            range: _,
            node_index: _,
            value,
            ctx: _,
        } = starred;

        self.store_type_expression_flags(ast::ExprRef::from(starred), TypeExpressionFlags::UNPACK);

        let previously_in_unpack_type_argument = self
            .context
            .inference_flags
            .replace(InferenceFlags::IN_UNPACK_TYPE_ARGUMENT, true);
        let starred_type = self.infer_type_expression(value);
        self.context.inference_flags.set(
            InferenceFlags::IN_UNPACK_TYPE_ARGUMENT,
            previously_in_unpack_type_argument,
        );

        if starred_type.exact_tuple_instance_spec(self.db()).is_some()
            || matches!(
                starred_type,
                Type::TypeVar(typevar) if typevar.is_typevartuple(self.db())
            )
        {
            starred_type
        } else {
            self.store_type_expression_flags(
                ast::ExprRef::from(starred),
                TypeExpressionFlags::INVALID_UNPACK,
            );
            if !starred_type.is_unknown()
                && let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, starred)
            {
                diagnostic::add_type_expression_reference_link(
                    builder.into_diagnostic("`*` can only unpack a tuple type or `TypeVarTuple`"),
                );
            }
            Type::homogeneous_tuple(self.db(), Type::unknown())
        }
    }

    pub(super) fn infer_subscript_type_expression_no_store(
        &mut self,
        subscript: &ast::ExprSubscript,
        slice: &ast::Expr,
        value_ty: Type<'db>,
    ) -> Type<'db> {
        match value_ty {
            Type::ClassLiteral(class_literal) => match class_literal.known(self.db()) {
                Some(KnownClass::Tuple) => Type::tuple(self.infer_tuple_type_expression(subscript)),
                Some(KnownClass::Type) => self.infer_subclass_of_type_expression(slice),
                _ => self.infer_subscript_type_expression(subscript, value_ty),
            },
            _ => self.infer_subscript_type_expression(subscript, value_ty),
        }
    }

    /// Infer the type of a string type expression.
    pub(super) fn infer_string_type_expression(
        &mut self,
        string: &ast::ExprStringLiteral,
    ) -> Type<'db> {
        match parse_string_annotation(&self.context, self.inference_flags(), string) {
            Some(parsed) => {
                self.string_annotations
                    .insert(ruff_python_ast::ExprRef::StringLiteral(string).into());
                // String annotations are always evaluated in the deferred context.
                let parsed_expr = parsed.expr();
                let string_was_nested = self
                    .inference_flags()
                    .contains(InferenceFlags::IN_NESTED_TYPE_EXPRESSION);
                let previously_in_type_expression = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::IN_TYPE_EXPRESSION, false);
                let previously_in_nested_type_expression = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::IN_NESTED_TYPE_EXPRESSION, string_was_nested);
                let ty = self.infer_type_expression_with_state(
                    parsed_expr,
                    DeferredExpressionState::InStringAnnotation(
                        self.enclosing_node_key(string.into()),
                    ),
                );
                self.context.inference_flags.set(
                    InferenceFlags::IN_NESTED_TYPE_EXPRESSION,
                    previously_in_nested_type_expression,
                );
                self.context.inference_flags.set(
                    InferenceFlags::IN_TYPE_EXPRESSION,
                    previously_in_type_expression,
                );
                let parsed_flags = self.type_expression_flags(parsed_expr);
                if !parsed_flags.is_empty() {
                    self.store_type_expression_flags(
                        ruff_python_ast::ExprRef::StringLiteral(string),
                        parsed_flags,
                    );
                }
                ty
            }
            None => Type::unknown(),
        }
    }

    /// Return the type represented by a `tuple[]` expression in a type annotation.
    ///
    /// This method assumes that a type has already been inferred and stored for the `value`
    /// of the subscript passed in.
    pub(super) fn infer_tuple_type_expression(
        &mut self,
        tuple: &ast::ExprSubscript,
    ) -> Option<TupleType<'db>> {
        match &*tuple.slice {
            ast::Expr::Tuple(elements) => {
                if let [element, ellipsis @ ast::Expr::EllipsisLiteral(_)] = &*elements.elts {
                    self.infer_expression(ellipsis, TypeContext::default());
                    let previously_in_valid_unpack_context = self
                        .context
                        .inference_flags
                        .replace(InferenceFlags::IN_VALID_UNPACK_CONTEXT, true);
                    let element_ty = self.infer_type_expression(element);
                    self.context.inference_flags.set(
                        InferenceFlags::IN_VALID_UNPACK_CONTEXT,
                        previously_in_valid_unpack_context,
                    );
                    if self
                        .type_expression_flags(element)
                        .contains(TypeExpressionFlags::UNPACK)
                        && let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, tuple)
                    {
                        let mut diagnostic =
                            builder.into_diagnostic("Invalid `tuple` specialization");
                        diagnostic
                            .set_primary_message("`...` cannot be used after an unpacked element");
                    }
                    let result = TupleType::homogeneous(self.db(), element_ty);
                    self.store_expression_type(&tuple.slice, Type::tuple(Some(result)));
                    return Some(result);
                }

                let mut element_types = TupleSpecBuilder::with_capacity(elements.len());

                let mut first_unpacked_variadic_tuple = None;

                for element in elements {
                    if element.is_ellipsis_literal_expr() {
                        if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, tuple) {
                            let mut diagnostic =
                                builder.into_diagnostic("Invalid `tuple` specialization");
                            diagnostic.set_primary_message(
                                "`...` can only be used as the second element \
                                in a two-element `tuple` specialization",
                            );
                        }
                        self.store_expression_type(element, Type::unknown());
                        element_types.push(Type::unknown());
                        continue;
                    }
                    let previously_in_valid_unpack_context = self
                        .context
                        .inference_flags
                        .replace(InferenceFlags::IN_VALID_UNPACK_CONTEXT, true);
                    let element_ty = self.infer_type_expression(element);
                    self.context.inference_flags.set(
                        InferenceFlags::IN_VALID_UNPACK_CONTEXT,
                        previously_in_valid_unpack_context,
                    );
                    // Determine if this element unpacks a tuple: either `*expr` or `Unpack[expr]`
                    let is_unpack = matches!(element, ast::Expr::Starred(_))
                        || matches!(
                            element,
                            ast::Expr::Subscript(ast::ExprSubscript { value, .. })
                                if self.expression_type(value)
                                    == Type::SpecialForm(SpecialFormType::Unpack)
                        );

                    if is_unpack {
                        let mut report_too_many_unpacked_tuples = || {
                            if let Some(first_unpacked_variadic_tuple) =
                                first_unpacked_variadic_tuple
                            {
                                if let Some(builder) =
                                    self.context.report_lint(&INVALID_TYPE_FORM, tuple)
                                {
                                    let mut diagnostic = builder.into_diagnostic(
                                        "Multiple unpacked variadic tuples \
                                            are not allowed in a `tuple` specialization",
                                    );
                                    diagnostic.annotate(
                                        self.context
                                            .secondary(first_unpacked_variadic_tuple)
                                            .message("First unpacked variadic tuple"),
                                    );
                                    diagnostic.annotate(
                                        self.context
                                            .secondary(element)
                                            .message("Later unpacked variadic tuple"),
                                    );
                                }
                            } else {
                                first_unpacked_variadic_tuple = Some(element);
                            }
                        };

                        if let Some(inner_tuple) = element_ty.exact_tuple_instance_spec(self.db()) {
                            element_types = element_types.concat(self.db(), &inner_tuple);

                            if inner_tuple.is_variadic() {
                                report_too_many_unpacked_tuples();
                            }
                        } else if let Type::TypeVar(typevar) = element_ty
                            && typevar.is_typevartuple(self.db())
                        {
                            report_too_many_unpacked_tuples();
                            element_types =
                                element_types.concat_variadic_typevar(self.db(), typevar);
                        } else {
                            // TODO: emit a diagnostic
                        }
                    } else {
                        element_types.push(element_ty);
                    }
                }

                let ty = TupleType::new(self.db(), &element_types.build());

                // Here, we store the type for the inner `int, str` tuple-expression,
                // while the type for the outer `tuple[int, str]` slice-expression is
                // stored in the surrounding `infer_type_expression` call:
                self.store_expression_type(&tuple.slice, Type::tuple(ty));

                ty
            }
            single_element => {
                if single_element.is_ellipsis_literal_expr() {
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, tuple) {
                        let mut diagnostic =
                            builder.into_diagnostic("Invalid `tuple` specialization");
                        diagnostic.set_primary_message(
                            "`...` can only be used as the second element \
                                in a two-element `tuple` specialization",
                        );
                    }
                    self.store_expression_type(single_element, Type::unknown());
                    return TupleType::heterogeneous(self.db(), std::iter::once(Type::unknown()));
                }
                let previously_in_valid_unpack_context = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::IN_VALID_UNPACK_CONTEXT, true);
                let single_element_ty = self.infer_type_expression(single_element);
                self.context.inference_flags.set(
                    InferenceFlags::IN_VALID_UNPACK_CONTEXT,
                    previously_in_valid_unpack_context,
                );
                let single_element_is_unpack = matches!(single_element, ast::Expr::Starred(_))
                    || matches!(
                        single_element,
                        ast::Expr::Subscript(ast::ExprSubscript { value, .. })
                            if self.expression_type(value)
                                == Type::SpecialForm(SpecialFormType::Unpack)
                    );
                if single_element_is_unpack {
                    if let Some(inner_tuple) =
                        single_element_ty.exact_tuple_instance_spec(self.db())
                    {
                        return TupleType::new(self.db(), &inner_tuple);
                    } else if let Type::TypeVar(typevar) = single_element_ty
                        && typevar.is_typevartuple(self.db())
                    {
                        return TupleType::new(
                            self.db(),
                            &TupleSpecBuilder::with_capacity(0)
                                .concat_variadic_typevar(self.db(), typevar)
                                .build(),
                        );
                    }
                }
                TupleType::heterogeneous(self.db(), std::iter::once(single_element_ty))
            }
        }
    }

    /// Given the slice of a `type[]` annotation, return the type that the annotation represents
    fn infer_subclass_of_type_expression(&mut self, slice: &ast::Expr) -> Type<'db> {
        let invalid_type_argument = |builder: &Self, slice: &ast::Expr| {
            builder.report_invalid_type_expression(
                slice,
                "The argument to `type[]` must be a class object type",
            );
            SubclassOfType::subclass_of_unknown()
        };

        let subclass_of_type_argument = |builder: &Self, slice: &ast::Expr, slice_ty: Type<'db>| {
            let slice_ty = slice_ty.resolve_type_alias(builder.db());
            let slice_ty = match slice_ty {
                Type::Union(union) if union.has_aliases(builder.db()) => {
                    union.expand_aliases(builder.db())
                }
                _ => slice_ty,
            };
            SubclassOfType::try_from_instance(builder.db(), slice_ty).unwrap_or_else(|| {
                match slice_ty {
                    Type::Callable(_) => invalid_type_argument(builder, slice),
                    _ => todo_type!("unsupported type[X] special form"),
                }
            })
        };

        let infer_type_argument = |builder: &mut Self, slice: &ast::Expr| {
            let slice_ty = builder.infer_type_expression(slice);
            subclass_of_type_argument(builder, slice, slice_ty)
        };

        match slice {
            ast::Expr::Name(_) | ast::Expr::Attribute(_) | ast::Expr::StringLiteral(_) => {
                infer_type_argument(self, slice)
            }
            ast::Expr::BinOp(binary) if binary.op == ast::Operator::BitOr => {
                infer_type_argument(self, slice)
            }
            ast::Expr::Tuple(_) => {
                if !self.in_string_annotation() {
                    self.infer_expression(slice, TypeContext::default());
                }
                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, slice) {
                    builder.into_diagnostic("type[...] must have exactly one type argument");
                }
                Type::unknown()
            }
            ast::Expr::NoneLiteral(_) => {
                self.infer_expression(slice, TypeContext::default());
                KnownClass::NoneType.to_subclass_of(self.db())
            }
            ast::Expr::Subscript(
                subscript @ ast::ExprSubscript {
                    value,
                    slice: parameters,
                    ..
                },
            ) => {
                let parameters_ty = match self.infer_expression(value, TypeContext::default()) {
                    Type::SpecialForm(SpecialFormType::Union) => match &**parameters {
                        ast::Expr::Tuple(tuple) => {
                            let ty = UnionType::from_elements_leave_aliases(
                                self.db(),
                                tuple
                                    .iter()
                                    .map(|element| self.infer_subclass_of_type_expression(element)),
                            );
                            self.store_expression_type(parameters, ty);
                            ty
                        }
                        _ => self.infer_subclass_of_type_expression(parameters),
                    },
                    value_ty @ Type::ClassLiteral(class_literal) => {
                        if class_literal.is_tuple(self.db()) {
                            let class_type = self
                                .infer_tuple_type_expression(subscript)
                                .map(|tuple_type| tuple_type.to_class_type(self.db()))
                                .unwrap_or_else(|| class_literal.default_specialization(self.db()));
                            SubclassOfType::from(self.db(), class_type)
                        } else {
                            match class_literal.generic_context(self.db()) {
                                Some(generic_context) => {
                                    let db = self.db();
                                    let specialize = &|types: &[Option<Type<'db>>]| {
                                        let class = class_literal.apply_specialization(db, |_| {
                                            generic_context
                                                .specialize_partial(db, types.iter().copied())
                                        });
                                        if class_literal.is_protocol(db) {
                                            match Type::instance(db, class) {
                                                Type::ProtocolInstance(protocol) => {
                                                    SubclassOfType::from_protocol(protocol)
                                                }
                                                _ => SubclassOfType::from(db, class),
                                            }
                                        } else {
                                            SubclassOfType::from(db, class)
                                        }
                                    };
                                    self.infer_explicit_callable_specialization(
                                        subscript,
                                        value_ty,
                                        generic_context,
                                        specialize,
                                    )
                                }
                                None => {
                                    // TODO: emit a diagnostic if you try to specialize a non-generic class.
                                    self.infer_expression(parameters, TypeContext::default());
                                    todo_type!("specialized non-generic class")
                                }
                            }
                        }
                    }
                    Type::SpecialForm(
                        special_form @ (SpecialFormType::TypingCallable
                        | SpecialFormType::CollectionsAbcCallable),
                    ) => {
                        self.infer_parameterized_special_form_type_expression(
                            subscript,
                            special_form,
                        );
                        invalid_type_argument(self, slice)
                    }
                    value_ty @ Type::KnownInstance(KnownInstanceType::TypeAliasType(
                        TypeAliasType::PEP695(_),
                    )) => {
                        let slice_ty = self.infer_subscript_type_expression(subscript, value_ty);
                        subclass_of_type_argument(self, slice, slice_ty)
                    }
                    _ => {
                        self.infer_expression(parameters, TypeContext::default());
                        todo_type!("unsupported nested subscript in type[X]")
                    }
                };
                self.store_expression_type(slice, parameters_ty);
                parameters_ty
            }
            _ => {
                self.infer_expression(slice, TypeContext::default());
                todo_type!("unsupported type[X] special form")
            }
        }
    }

    /// Infer the type of an explicitly specialized generic type alias (implicit or PEP 613).
    pub(crate) fn infer_explicit_type_alias_specialization(
        &mut self,
        subscript: &ast::ExprSubscript,
        mut value_ty: Type<'db>,
        in_type_expression: bool,
    ) -> Type<'db> {
        let db = self.db();

        if let Type::KnownInstance(KnownInstanceType::TypeVar(typevar)) = value_ty
            && let Some(definition) = typevar.definition(db)
        {
            value_ty = value_ty.apply_type_mapping(
                db,
                &TypeMapping::BindLegacyTypevars(BindingContext::Definition(definition)),
                TypeContext::default(),
            );
        }

        let mut variables = FxOrderSet::default();
        value_ty.find_legacy_typevars(db, None, &mut variables);
        let generic_context = GenericContext::from_typevar_instances(db, variables);

        let scope_id = self.scope();
        let current_typevar_binding_context = self.typevar_binding_context;
        let current_inference_flags = self.inference_flags();

        // TODO
        // If we explicitly specialize a recursive generic (PEP-613 or implicit) type alias,
        // we currently miscount the number of type variables. For example, for a nested
        // dictionary type alias `NestedDict = dict[K, "V | NestedDict[K, V]"]]`, we might
        // infer `<class 'dict[K, Divergent]'>`, and therefore count just one type variable
        // instead of two. So until we properly support these, specialize all remaining type
        // variables with a `@Todo` type (since we don't know which of the type arguments
        // belongs to the remaining type variables).
        if any_over_type(self.db(), value_ty, true, |ty| ty.is_divergent()) {
            let value_ty = value_ty.apply_specialization(
                db,
                generic_context.specialize(
                    db,
                    std::iter::repeat_n(
                        todo_type!("specialized recursive generic type alias"),
                        generic_context.len(db),
                    )
                    .collect::<Vec<_>>(),
                ),
            );
            return if in_type_expression {
                value_ty
                    .in_type_expression(
                        db,
                        scope_id,
                        current_typevar_binding_context,
                        current_inference_flags,
                    )
                    .unwrap_or_else(|_| Type::unknown())
            } else {
                value_ty
            };
        }

        let specialize = &|types: &[Option<Type<'db>>]| {
            let specialized = value_ty.apply_specialization(
                db,
                generic_context.specialize_partial(db, types.iter().copied()),
            );

            if in_type_expression {
                specialized
                    .in_type_expression(
                        db,
                        scope_id,
                        current_typevar_binding_context,
                        current_inference_flags,
                    )
                    .unwrap_or_else(|_| Type::unknown())
            } else {
                specialized
            }
        };

        self.infer_explicit_callable_specialization(
            subscript,
            value_ty,
            generic_context,
            specialize,
        )
    }

    pub(super) fn infer_subscript_type_expression(
        &mut self,
        subscript: &ast::ExprSubscript,
        value_ty: Type<'db>,
    ) -> Type<'db> {
        let ast::ExprSubscript {
            range: _,
            node_index: _,
            value: _,
            slice,
            ctx: _,
        } = subscript;

        match value_ty {
            Type::Never => {
                // This case can be entered when we use a type annotation like `Literal[1]`
                // in unreachable code, since we infer `Never` for `Literal`.  We call
                // `infer_expression` (instead of `infer_type_expression`) here to avoid
                // false-positive `invalid-type-form` diagnostics (`1` is not a valid type
                // expression).
                if !self.in_string_annotation() {
                    self.infer_expression(slice, TypeContext::default());
                }
                Type::unknown()
            }
            Type::SpecialForm(special_form) => {
                self.infer_parameterized_special_form_type_expression(subscript, special_form)
            }
            Type::KnownInstance(known_instance) => match known_instance {
                KnownInstanceType::SubscriptedProtocol(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`typing.Protocol` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::SubscriptedGeneric(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`typing.Generic` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::Deprecated(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`warnings.deprecated` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::Field(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`dataclasses.Field` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::ConstraintSet(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`ty_extensions._internal.ConstraintSet` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::ConstraintSetSolution(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`ty_extensions._internal.ConstraintSetSolution` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::GenericContext(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`ty_extensions._internal.GenericContext` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::Specialization(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`ty_extensions._internal.Specialization` is not allowed in {}s",
                            self.type_expression_context(),
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::TypeAliasType(type_alias @ TypeAliasType::PEP695(_)) => {
                    match type_alias.generic_context(self.db()) {
                        Some(generic_context) => {
                            let specialized_type_alias = self
                                .infer_explicit_type_alias_type_specialization(
                                    subscript,
                                    value_ty,
                                    type_alias,
                                    generic_context,
                                );

                            specialized_type_alias
                                .in_type_expression(
                                    self.db(),
                                    self.scope(),
                                    self.typevar_binding_context,
                                    self.inference_flags(),
                                )
                                .unwrap_or(Type::unknown())
                        }
                        None => {
                            if !self.in_string_annotation() {
                                self.infer_expression(slice, TypeContext::default());
                            }
                            if let Some(builder) =
                                self.context.report_lint(&NOT_SUBSCRIPTABLE, subscript)
                            {
                                let mut diagnostic = builder.into_diagnostic(format_args!(
                                    "Cannot specialize non-generic type alias `{}`",
                                    type_alias.name(self.db())
                                ));
                                let secondary = self.context.secondary(&*subscript.value);
                                let value_type = type_alias.raw_value_type(self.db());
                                if value_type.is_specialized_generic(self.db()) {
                                    diagnostic.annotate(secondary.message(format_args!(
                                        "Alias to `{}`, which is already specialized",
                                        value_type.display(self.db())
                                    )));
                                } else {
                                    diagnostic.annotate(secondary.message(format_args!(
                                        "Alias to `{}`, which is not generic",
                                        value_type.display(self.db())
                                    )));
                                }
                            }

                            Type::unknown()
                        }
                    }
                }
                KnownInstanceType::TypeAliasType(TypeAliasType::ManualPEP695(_)) => {
                    // TODO: support generic "manual" PEP 695 type aliases
                    let slice_ty = self.infer_expression(slice, TypeContext::default());
                    let mut variables = FxOrderSet::default();
                    slice_ty.bind_and_find_all_legacy_typevars(
                        self.db(),
                        self.typevar_binding_context,
                        &mut variables,
                    );
                    let generic_context =
                        GenericContext::from_typevar_instances(self.db(), variables);
                    Type::Dynamic(DynamicType::UnknownGeneric(generic_context))
                }
                KnownInstanceType::Literal(ty) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`{ty}` is not a generic class",
                            ty = ty.inner(self.db()).display(self.db())
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::TypeVar(typevar) => {
                    // The type variable designated as a generic type alias by `typing.TypeAlias` can be explicitly specialized.
                    // ```py
                    // from typing import TypeVar, TypeAlias
                    // T = TypeVar('T')
                    // Annotated: TypeAlias = T
                    // _: Annotated[int] = 1  # valid
                    // ```
                    if typevar.identity(self.db()).kind(self.db()) == TypeVarKind::Pep613Alias {
                        self.infer_explicit_type_alias_specialization(subscript, value_ty, false)
                    } else {
                        if !self.in_string_annotation() {
                            self.infer_expression(slice, TypeContext::default());
                        }
                        if let Some(builder) =
                            self.context.report_lint(&INVALID_TYPE_FORM, subscript)
                        {
                            builder.into_diagnostic(format_args!(
                                "A type variable itself cannot be specialized",
                            ));
                        }
                        Type::unknown()
                    }
                }
                KnownInstanceType::LiteralStringAlias(_)
                | KnownInstanceType::UnionType(_)
                | KnownInstanceType::Callable(_)
                | KnownInstanceType::Annotated(_)
                | KnownInstanceType::TypeGenericAlias(_) => {
                    self.infer_explicit_type_alias_specialization(subscript, value_ty, true)
                }
                KnownInstanceType::NewType(newtype) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(&subscript.slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`{}` is a `NewType` and cannot be specialized",
                            newtype.name(self.db())
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::Sentinel(sentinel) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(&subscript.slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`{}` is a sentinel and cannot be specialized",
                            sentinel.name(self.db())
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::NamedTupleSpec(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(&subscript.slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`NamedTuple` specs cannot be specialized",
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::FunctoolsPartial(_)
                | KnownInstanceType::FunctoolsPartialCall(_) => {
                    self.infer_type_expression(&subscript.slice);
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`functools.partial` instances cannot be specialized",
                        ));
                    }
                    Type::unknown()
                }
                KnownInstanceType::Range { .. } => {
                    if !self.in_string_annotation() {
                        self.infer_expression(&subscript.slice, TypeContext::default());
                    }
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        builder.into_diagnostic(format_args!(
                            "`range` instances cannot be specialized"
                        ));
                    }
                    Type::unknown()
                }
            },
            Type::Dynamic(DynamicType::UnknownGeneric(_)) => {
                self.infer_explicit_type_alias_specialization(subscript, value_ty, true)
            }
            Type::Dynamic(_) | Type::Divergent(_) => {
                // Infer slice as a value expression to avoid false-positive
                // `invalid-type-form` diagnostics, when we have e.g.
                // `MyCallable[[int, str], None]` but `MyCallable` is dynamic.
                if !self.in_string_annotation() {
                    self.infer_expression(slice, TypeContext::default());
                }
                value_ty
            }
            Type::ClassLiteral(class) => {
                match (class.generic_context(self.db()), class.as_static()) {
                    (Some(generic_context), Some(static_class)) => {
                        let specialized_class = self.infer_explicit_class_specialization(
                            subscript,
                            value_ty,
                            static_class,
                            generic_context,
                        );

                        specialized_class
                            .in_type_expression(
                                self.db(),
                                self.scope(),
                                self.typevar_binding_context,
                                self.inference_flags(),
                            )
                            .unwrap_or(Type::unknown())
                    }
                    _ => {
                        // TODO: emit a diagnostic if you try to specialize a non-generic class.
                        self.infer_expression(slice, TypeContext::default());
                        todo_type!("specialized non-generic class")
                    }
                }
            }
            Type::GenericAlias(_) => {
                self.infer_explicit_type_alias_specialization(subscript, value_ty, true)
            }
            Type::LiteralValue(literal) if literal.is_string() => {
                self.infer_expression(slice, TypeContext::default());
                // For stringified TypeAlias; remove once properly supported
                todo_type!("string literal subscripted in type expression")
            }
            Type::Union(union) => {
                let db = self.db();
                let mut union_builder =
                    UnionBuilder::new(db).recursively_defined(union.recursively_defined(db));

                for (index, element) in union.elements(db).iter().enumerate() {
                    let mut speculative_builder = self.speculate();
                    let subscript_ty =
                        speculative_builder.infer_subscript_type_expression(subscript, *element);
                    if index == 0 {
                        self.extend(speculative_builder);
                    } else {
                        self.context.extend(&speculative_builder.context.finish());
                    }
                    union_builder = union_builder.add(subscript_ty);
                }

                union_builder.build()
            }
            _ => {
                if !self.in_string_annotation() {
                    self.infer_expression(slice, TypeContext::default());
                }
                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    builder.into_diagnostic(format_args!(
                        "Invalid subscript of object of type `{}` in a {}",
                        value_ty.display(self.db()),
                        self.type_expression_context()
                    ));
                }
                Type::unknown()
            }
        }
    }

    fn infer_parameterized_legacy_typing_alias(
        &mut self,
        subscript_node: &ast::ExprSubscript,
        alias: LegacyStdlibAlias,
    ) -> Type<'db> {
        let arguments = &*subscript_node.slice;
        let args = if let ast::Expr::Tuple(t) = arguments {
            &*t.elts
        } else {
            std::slice::from_ref(arguments)
        };

        let AliasSpec {
            class,
            expected_argument_number,
        } = alias.alias_spec();

        if args.len() != expected_argument_number {
            if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript_node) {
                let noun = if expected_argument_number == 1 {
                    "argument"
                } else {
                    "arguments"
                };
                builder.into_diagnostic(format_args!(
                    "Legacy alias `{alias}` expected exactly {expected_argument_number} {noun}, \
                    got {}",
                    args.len()
                ));
            }
        }
        let ty = class.to_specialized_instance(
            self.db(),
            args.iter()
                .map(|node| self.infer_type_expression(node))
                .collect::<Vec<_>>(),
        );
        if arguments.is_tuple_expr() {
            self.store_expression_type(arguments, ty);
        }
        ty
    }

    /// Infer the type of a `Callable[...]` type expression.
    pub(crate) fn infer_callable_type(&mut self, subscript: &ast::ExprSubscript) -> Type<'db> {
        fn inner<'db>(
            builder: &mut TypeInferenceBuilder<'db, '_>,
            subscript: &ast::ExprSubscript,
        ) -> Type<'db> {
            let db = builder.db();

            let arguments_slice = &*subscript.slice;

            let mut arguments = match arguments_slice {
                ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
                _ => {
                    builder.infer_callable_parameter_types(arguments_slice);
                    Either::Right(std::iter::empty::<&ast::Expr>())
                }
            };

            let first_argument = arguments.next();

            let previously_allowed_concatenate = builder
                .context
                .inference_flags
                .replace(InferenceFlags::IN_VALID_CONCATENATE_CONTEXT, true);
            let parameters =
                first_argument.and_then(|arg| builder.infer_callable_parameter_types(arg));
            builder.context.inference_flags.set(
                InferenceFlags::IN_VALID_CONCATENATE_CONTEXT,
                previously_allowed_concatenate,
            );

            let return_type = arguments
                .next()
                .map(|arg| builder.infer_type_expression(arg));

            let callable_type = if parameters.is_none()
                && let Some(first_argument) = first_argument
                && let ast::Expr::List(list) = first_argument
                && let [single_param] = &list.elts[..]
                && single_param.is_ellipsis_literal_expr()
            {
                builder.store_expression_type(single_param, Type::unknown());
                if let Some(mut diagnostic) = builder.report_invalid_type_expression(
                    first_argument,
                    "`[...]` is not a valid parameter list for `Callable`",
                ) {
                    if let Some(returns) = return_type {
                        diagnostic.set_primary_message(format_args!(
                            "Did you mean `Callable[..., {}]`?",
                            returns.display(db)
                        ));
                    }
                }
                Type::single_callable(
                    db,
                    Signature::new(
                        Parameters::unknown(),
                        return_type.unwrap_or_else(Type::unknown),
                    ),
                )
            } else {
                let correct_argument_number = if let Some(third_argument) = arguments.next() {
                    builder.infer_type_expression(third_argument);
                    for argument in arguments {
                        builder.infer_type_expression(argument);
                    }
                    false
                } else {
                    return_type.is_some()
                };

                if !correct_argument_number {
                    report_invalid_arguments_to_callable(&builder.context, subscript);
                }

                if correct_argument_number
                    && let (Some(parameters), Some(return_type)) = (parameters, return_type)
                {
                    Type::single_callable(db, Signature::new(parameters, return_type))
                } else {
                    Type::Callable(CallableType::unknown(db))
                }
            };

            // `Signature` / `Parameters` are not a `Type` variant, so we're storing
            // the outer callable type on these expressions instead.
            builder.store_expression_type(arguments_slice, callable_type);
            if let Some(first_argument) = first_argument {
                builder.store_expression_type(first_argument, callable_type);
            }

            callable_type
        }

        // There is disagreement among type checkers about whether `Callable` annotations
        // in the global scope or similar should be considered to create an implicit generic context.
        // For now, we do not report unbound type variables in any `Callable` contexts, but we may
        // decide to revisit this in the future.
        let previous_check_unbound_typevars = self
            .context
            .inference_flags
            .replace(InferenceFlags::CHECK_UNBOUND_TYPEVARS, false);
        let result = inner(self, subscript);
        self.context.inference_flags.set(
            InferenceFlags::CHECK_UNBOUND_TYPEVARS,
            previous_check_unbound_typevars,
        );
        result
    }

    fn infer_parameterized_special_form_type_expression(
        &mut self,
        subscript: &ast::ExprSubscript,
        special_form: SpecialFormType,
    ) -> Type<'db> {
        let db = self.db();
        let arguments_slice = &*subscript.slice;
        match special_form {
            SpecialFormType::Annotated => self
                .parse_subscription_of_annotated_special_form(
                    subscript,
                    AnnotatedExprContext::TypeExpression,
                )
                .inner_type()
                .in_type_expression(self.db(), self.scope(), None, self.inference_flags())
                .unwrap_or_else(|err| {
                    err.into_fallback_type(&self.context, subscript, self.inference_flags())
                }),
            SpecialFormType::Literal => match self.infer_literal_parameter_type(arguments_slice) {
                Ok(ty) => ty,
                Err(nodes) => {
                    for node in nodes {
                        let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, node)
                        else {
                            continue;
                        };
                        builder.into_diagnostic(
                            "Type arguments for `Literal` must be `None`, \
                            a literal value (int, bool, str, or bytes), or an enum member",
                        );
                    }
                    Type::unknown()
                }
            },
            SpecialFormType::Optional => {
                let param_type = self.infer_type_expression(arguments_slice);
                UnionType::from_elements_leave_aliases(db, [param_type, Type::none(db)])
            }
            SpecialFormType::Union => {
                // TODO: Support the union of a `TypeVarTuple`'s elements. Until then, reject
                // `Union[*Ts]` and recover to `object` rather than treating `Ts` as one member.
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let mut has_unpacked_typevartuple = false;
                let union_ty = UnionType::from_elements_leave_aliases(
                    db,
                    arguments.iter().map(|argument| {
                        let ty = self.infer_type_expression(argument);
                        if self
                            .type_expression_flags(argument)
                            .contains(TypeExpressionFlags::UNPACK)
                        {
                            let is_typevartuple = matches!(
                                ty,
                                Type::TypeVar(typevar) if typevar.is_typevartuple(db)
                            ) || if let ast::Expr::Subscript(subscript) = argument {
                                let previously_in_unpack_type_argument = self
                                    .context
                                    .inference_flags
                                    .replace(InferenceFlags::IN_UNPACK_TYPE_ARGUMENT, true);
                                let inner_ty = self.infer_type_expression(&subscript.slice);
                                self.context.inference_flags.set(
                                    InferenceFlags::IN_UNPACK_TYPE_ARGUMENT,
                                    previously_in_unpack_type_argument,
                                );
                                matches!(
                                    inner_ty,
                                    Type::TypeVar(typevar) if typevar.is_typevartuple(db)
                                )
                            } else {
                                false
                            };
                            if is_typevartuple {
                                has_unpacked_typevartuple = true;
                                if !ty.is_unknown()
                                    && let Some(builder) =
                                        self.context.report_lint(&INVALID_TYPE_FORM, argument)
                                {
                                    diagnostic::add_type_expression_reference_link(
                                        builder.into_diagnostic(
                                            "Unpacking a `TypeVarTuple` in `Union` is not supported",
                                        ),
                                    );
                                }
                            }
                        }
                        ty
                    }),
                );
                let ty = if has_unpacked_typevartuple {
                    Type::object()
                } else {
                    union_ty
                };
                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, ty);
                }
                ty
            }
            SpecialFormType::TypingCallable | SpecialFormType::CollectionsAbcCallable => {
                self.infer_callable_type(subscript)
            }

            // `ty_extensions` special forms
            SpecialFormType::Not => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let num_arguments = arguments.len();
                let negated_type = if num_arguments == 1 {
                    self.infer_type_expression(&arguments[0]).negate(db)
                } else {
                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );
                    Type::unknown()
                };
                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, negated_type);
                }
                negated_type
            }
            SpecialFormType::Intersection => {
                let elements = match arguments_slice {
                    ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
                    element => Either::Right(std::iter::once(element)),
                };

                let ty = elements
                    .fold(IntersectionBuilder::new(db), |builder, element| {
                        builder.add_positive(self.infer_type_expression(element))
                    })
                    .build();

                if matches!(arguments_slice, ast::Expr::Tuple(_)) {
                    self.store_expression_type(arguments_slice, ty);
                }
                ty
            }
            SpecialFormType::Top => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let num_arguments = arguments.len();
                let arg = if num_arguments == 1 {
                    self.infer_type_expression(&arguments[0])
                } else {
                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );
                    Type::unknown()
                };
                arg.top_materialization(db)
            }
            SpecialFormType::Bottom => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let num_arguments = arguments.len();
                let arg = if num_arguments == 1 {
                    self.infer_type_expression(&arguments[0])
                } else {
                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );
                    Type::unknown()
                };
                arg.bottom_materialization(db)
            }
            SpecialFormType::TypeOf => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let num_arguments = arguments.len();
                let type_of_type = if num_arguments == 1 {
                    // N.B. This uses `infer_expression` rather than `infer_type_expression`
                    self.infer_expression(&arguments[0], TypeContext::default())
                } else {
                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );
                    Type::unknown()
                };
                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, type_of_type);
                }
                type_of_type
            }
            SpecialFormType::TypeForm => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let type_argument = if let [argument] = arguments {
                    self.infer_type_expression(argument)
                } else {
                    let num_arguments = arguments.len();

                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );

                    Type::unknown()
                };
                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, type_argument);
                }
                TypeFormType::from_type_expression(db, type_argument)
            }

            SpecialFormType::CallableTypeOf | SpecialFormType::RegularCallableTypeOf => {
                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };
                let num_arguments = arguments.len();

                if num_arguments != 1 {
                    if !self.in_string_annotation() {
                        for argument in arguments {
                            self.infer_expression(argument, TypeContext::default());
                        }
                    }
                    report_invalid_argument_number_to_special_form(
                        &self.context,
                        subscript,
                        special_form,
                        num_arguments,
                        1,
                    );
                    if arguments_slice.is_tuple_expr() {
                        self.store_expression_type(arguments_slice, Type::unknown());
                    }
                    return Type::unknown();
                }

                let argument_type = self.infer_expression(&arguments[0], TypeContext::default());

                let Some(callable_type) = argument_type
                    .try_upcast_to_callable_with_recursive_fallback(
                        db,
                        self.recursive_type_expression_definition(),
                    )
                    .map(|callables| {
                        if special_form == SpecialFormType::RegularCallableTypeOf {
                            callables
                                .map(|callable| callable.into_regular(db))
                                .into_type(db)
                        } else {
                            callables.into_type(db)
                        }
                    })
                else {
                    if let Some(builder) = self
                        .context
                        .report_lint(&INVALID_TYPE_FORM, arguments_slice)
                    {
                        builder.into_diagnostic(format_args!(
                            "Expected the first argument to `{special_form}` \
                                 to be a callable object, \
                                 but got an object of type `{actual_type}`",
                            actual_type = argument_type.display(db)
                        ));
                    }
                    if arguments_slice.is_tuple_expr() {
                        self.store_expression_type(arguments_slice, Type::unknown());
                    }
                    return Type::unknown();
                };

                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, callable_type);
                }
                callable_type
            }
            SpecialFormType::LegacyStdlibAlias(alias) => {
                self.infer_parameterized_legacy_typing_alias(subscript, alias)
            }
            SpecialFormType::TypeQualifier(qualifier) => {
                if self.inference_flags().intersects(
                    InferenceFlags::IN_PARAMETER_ANNOTATION
                        | InferenceFlags::IN_RETURN_TYPE
                        | InferenceFlags::IN_TYPE_ALIAS,
                ) {
                    self.report_invalid_type_expression(
                        subscript,
                        format_args!(
                            "Type qualifier `{qualifier}` is not allowed in {}s",
                            self.inference_flags().type_expression_context(),
                        ),
                    );
                } else {
                    self.report_invalid_type_expression(
                        subscript,
                        format_args!(
                            "Type qualifier `{qualifier}` is not allowed in type expressions \
                            (only in annotation expressions)",
                        ),
                    );
                }
                self.infer_type_expression(arguments_slice)
            }
            SpecialFormType::TypeIs => match arguments_slice {
                ast::Expr::Tuple(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(arguments_slice, TypeContext::default());
                    }

                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        let diag = builder.into_diagnostic(
                            "Special form `typing.TypeIs` expected exactly one type parameter",
                        );
                        diagnostic::add_type_expression_reference_link(diag);
                    }

                    Type::unknown()
                }
                _ => {
                    let narrowed = self.infer_type_expression(arguments_slice);
                    let expanded = narrowed.expand_eagerly(self.db());

                    if expanded.is_divergent() {
                        expanded
                    } else {
                        TypeIsType::from_type_expression(self.db(), narrowed)
                    }
                }
            },
            SpecialFormType::TypeGuard => match arguments_slice {
                ast::Expr::Tuple(_) => {
                    if !self.in_string_annotation() {
                        self.infer_expression(arguments_slice, TypeContext::default());
                    }

                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        let diag = builder.into_diagnostic(
                            "Special form `typing.TypeGuard` expected exactly one type parameter",
                        );
                        diagnostic::add_type_expression_reference_link(diag);
                    }

                    Type::unknown()
                }
                _ => TypeGuardType::unbound(
                    self.db(),
                    // Unlike `TypeIs`, don't use top materialization, because
                    // `TypeGuard` clobbering behavior makes it counterintuitive
                    self.infer_type_expression(arguments_slice),
                ),
            },
            SpecialFormType::Concatenate => {
                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    let mut diag = builder.into_diagnostic(format_args!(
                        "`typing.Concatenate` is not allowed in this context in a {}",
                        self.type_expression_context()
                    ));
                    diag.info("`typing.Concatenate` is only valid:");
                    diag.info(" - as the first argument to `Callable`");
                    diag.info(" - as a type argument for a `ParamSpec` parameter");
                }

                let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
                    &*tuple.elts
                } else {
                    std::slice::from_ref(arguments_slice)
                };

                for (i, argument) in arguments.iter().enumerate() {
                    if argument.is_ellipsis_literal_expr() {
                        // The trailing `...` in `Concatenate[int, str, ...]` is valid;
                        // store without going through type-expression inference.
                        self.store_expression_type(argument, Type::unknown());
                    } else if i < arguments.len() - 1 {
                        let previously_allowed_paramspec = self
                            .context
                            .inference_flags
                            .replace(InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR, false);
                        self.infer_type_expression(argument);
                        self.context.inference_flags.set(
                            InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR,
                            previously_allowed_paramspec,
                        );
                    } else {
                        let previously_allowed_paramspec = self
                            .context
                            .inference_flags
                            .replace(InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR, true);
                        self.infer_type_expression(argument);
                        self.context.inference_flags.set(
                            InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR,
                            previously_allowed_paramspec,
                        );
                    }
                }

                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, Type::unknown());
                }

                Type::Dynamic(DynamicType::InvalidConcatenateUnknown)
            }
            SpecialFormType::Unpack => {
                self.store_type_expression_flags(
                    ast::ExprRef::from(subscript),
                    TypeExpressionFlags::UNPACK,
                );

                if self
                    .inference_flags()
                    .contains(InferenceFlags::IN_UNPACK_TYPE_ARGUMENT)
                {
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        diagnostic::add_type_expression_reference_link(
                            builder.into_diagnostic("`Unpack` cannot be nested"),
                        );
                    }
                    return Type::unknown();
                }

                if self
                    .inference_flags()
                    .contains(InferenceFlags::IN_KWARG_ANNOTATION)
                    && self
                        .inference_flags()
                        .contains(InferenceFlags::IN_NESTED_TYPE_EXPRESSION)
                {
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        diagnostic::add_type_expression_reference_link(builder.into_diagnostic(
                            "`Unpack` is only valid as the top-level `**kwargs` annotation form",
                        ));
                    }
                    return Type::unknown();
                }

                if !self.inference_flags().intersects(
                    InferenceFlags::IN_VARARG_ANNOTATION
                        | InferenceFlags::IN_KWARG_ANNOTATION
                        | InferenceFlags::IN_VALID_UNPACK_CONTEXT,
                ) {
                    if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                        diagnostic::add_type_expression_reference_link(builder.into_diagnostic(
                            format_args!(
                                "`Unpack` is not allowed in {}s",
                                self.type_expression_context()
                            ),
                        ));
                    }
                    return Type::unknown();
                }

                let previously_in_unpack_type_argument = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::IN_UNPACK_TYPE_ARGUMENT, true);
                let inner_ty = self.infer_type_expression(arguments_slice);
                self.context.inference_flags.set(
                    InferenceFlags::IN_UNPACK_TYPE_ARGUMENT,
                    previously_in_unpack_type_argument,
                );

                if self
                    .inference_flags()
                    .contains(InferenceFlags::IN_KWARG_ANNOTATION)
                {
                    return inner_ty;
                }

                // Preserve valid unpack targets so that `Unpack[...]` follows the same
                // argument-binding path as an equivalent starred annotation.
                if inner_ty.exact_tuple_instance_spec(self.db()).is_some()
                    || matches!(
                        inner_ty,
                        Type::TypeVar(typevar) if typevar.is_typevartuple(self.db())
                    )
                {
                    inner_ty
                } else {
                    self.store_type_expression_flags(
                        ast::ExprRef::from(subscript),
                        TypeExpressionFlags::INVALID_UNPACK,
                    );
                    if !inner_ty.is_unknown()
                        && let Some(builder) =
                            self.context.report_lint(&INVALID_TYPE_FORM, subscript)
                    {
                        diagnostic::add_type_expression_reference_link(builder.into_diagnostic(
                            "`Unpack` can only unpack a tuple type or `TypeVarTuple`",
                        ));
                    }
                    Type::homogeneous_tuple(self.db(), Type::unknown())
                }
            }
            SpecialFormType::NoReturn
            | SpecialFormType::Never
            | SpecialFormType::AlwaysTruthy
            | SpecialFormType::AlwaysFalsy => {
                if !self.in_string_annotation() {
                    self.infer_expression(arguments_slice, TypeContext::default());
                }

                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    builder.into_diagnostic(format_args!(
                        "Type `{special_form}` expected no type parameter",
                    ));
                }
                Type::unknown()
            }
            SpecialFormType::TypingSelf
            | SpecialFormType::TypeAlias
            | SpecialFormType::TypedDict(_)
            | SpecialFormType::Unknown
            | SpecialFormType::Divergent
            | SpecialFormType::Todo
            | SpecialFormType::Any
            | SpecialFormType::NamedTuple => {
                if !self.in_string_annotation() {
                    self.infer_expression(arguments_slice, TypeContext::default());
                }

                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    builder.into_diagnostic(format_args!(
                        "Special form `{special_form}` expected no type parameter",
                    ));
                }
                Type::unknown()
            }
            SpecialFormType::LiteralString => {
                let arguments = self.infer_expression(arguments_slice, TypeContext::default());

                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    let mut diag =
                        builder.into_diagnostic("`LiteralString` expects no type parameter");

                    let arguments_as_tuple = arguments.exact_tuple_instance_spec(db);

                    let argument_elements = arguments_as_tuple.as_ref().map_or_else(
                        || vec![arguments],
                        |tuple| tuple.iter_element_types(db).collect(),
                    );
                    let mut argument_elements = argument_elements.into_iter();

                    let probably_meant_literal = argument_elements.all(|ty| match ty {
                        Type::LiteralValue(literal)
                            if matches!(
                                literal.kind(),
                                LiteralValueTypeKind::String(_)
                                    | LiteralValueTypeKind::Bytes(_)
                                    | LiteralValueTypeKind::Enum(_)
                                    | LiteralValueTypeKind::Bool(_)
                            ) =>
                        {
                            true
                        }
                        Type::NominalInstance(instance) => {
                            instance.has_known_class(db, KnownClass::NoneType)
                        }
                        _ => false,
                    });

                    if probably_meant_literal {
                        diag.annotate(
                            self.context
                                .secondary(&*subscript.value)
                                .message("Did you mean `Literal`?"),
                        );
                        diag.set_concise_message(
                            "`LiteralString` expects no type parameter - did you mean `Literal`?",
                        );
                    }
                }
                Type::unknown()
            }
            SpecialFormType::Type => self.infer_subclass_of_type_expression(arguments_slice),
            SpecialFormType::Tuple => Type::tuple(self.infer_tuple_type_expression(subscript)),
            SpecialFormType::Generic | SpecialFormType::Protocol => {
                if !self.in_string_annotation() {
                    self.infer_expression(arguments_slice, TypeContext::default());
                }
                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    builder.into_diagnostic(format_args!(
                        "`{special_form}` is not allowed in {}s",
                        self.type_expression_context(),
                    ));
                }
                Type::unknown()
            }
        }
    }

    pub(crate) fn infer_literal_parameter_type<'param>(
        &mut self,
        parameters: &'param ast::Expr,
    ) -> Result<Type<'db>, Vec<&'param ast::Expr>> {
        let ty = match parameters {
            ast::Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => {
                let value_ty = self.infer_expression(value, TypeContext::default());
                if matches!(value_ty, Type::SpecialForm(SpecialFormType::Literal)) {
                    let ty = self.infer_literal_parameter_type(slice)?;

                    // This branch deals with annotations such as `Literal[Literal[1]]`.
                    // Here, we store the type for the inner `Literal[1]` expression:
                    self.store_expression_type(parameters, ty);
                    ty
                } else {
                    self.infer_expression(slice, TypeContext::default());
                    self.store_expression_type(parameters, Type::unknown());

                    return Err(vec![parameters]);
                }
            }
            ast::Expr::Tuple(tuple) if !tuple.parenthesized => {
                let mut errors = vec![];
                let mut builder = UnionBuilder::new(self.db());
                for elt in tuple {
                    match self.infer_literal_parameter_type(elt) {
                        Ok(ty) => {
                            builder = builder.add(ty);
                        }
                        Err(nodes) => {
                            errors.extend(nodes);
                        }
                    }
                }
                if errors.is_empty() {
                    let union_type = builder.build();

                    // This branch deals with annotations such as `Literal[1, 2]`. Here, we
                    // store the type for the inner `1, 2` tuple-expression:
                    self.store_expression_type(parameters, union_type);

                    union_type
                } else {
                    self.store_expression_type(parameters, Type::unknown());

                    return Err(errors);
                }
            }

            literal @ (ast::Expr::StringLiteral(_)
            | ast::Expr::BytesLiteral(_)
            | ast::Expr::BooleanLiteral(_)
            | ast::Expr::NoneLiteral(_)) => self.infer_expression(literal, TypeContext::default()),
            literal @ ast::Expr::NumberLiteral(number) if number.value.is_int() => {
                self.infer_expression(literal, TypeContext::default())
            }

            // for negative and positive numbers
            ast::Expr::UnaryOp(unary @ ast::ExprUnaryOp { op, operand, .. })
                if matches!(op, ast::UnaryOp::USub | ast::UnaryOp::UAdd)
                    && matches!(
                        &**operand,
                        ast::Expr::NumberLiteral(ast::ExprNumberLiteral {
                            value: ast::Number::Int(_),
                            ..
                        })
                    ) =>
            {
                let ty = self.infer_unary_expression(unary);
                self.store_expression_type(parameters, ty);
                ty
            }
            // enum members and aliases to literal types
            ast::Expr::Name(_) | ast::Expr::Attribute(_) => {
                let subscript_ty = self.infer_expression(parameters, TypeContext::default());
                match subscript_ty {
                    // type aliases to literal types
                    Type::KnownInstance(KnownInstanceType::TypeAliasType(type_alias)) => {
                        let value_ty = type_alias.value_type(self.db());
                        if value_ty.is_literal_or_union_of_literals(self.db()) {
                            return Ok(value_ty);
                        }
                    }
                    Type::KnownInstance(KnownInstanceType::Literal(ty)) => {
                        return Ok(ty.inner(self.db()));
                    }
                    // `Literal[SomeEnum.Member]`
                    Type::LiteralValue(literal) if literal.is_enum() => {
                        // Avoid promoting values originating from an explicitly annotated literal type.
                        return Ok(Type::LiteralValue(literal.to_unpromotable()));
                    }
                    // `Literal[SingletonEnum.Member]`, where `SingletonEnum.Member` simplifies to
                    // just `SingletonEnum`.
                    Type::NominalInstance(_) if subscript_ty.is_enum(self.db()) => {
                        return Ok(subscript_ty);
                    }
                    // suppress false positives for e.g. members of functional-syntax enums
                    Type::Dynamic(DynamicType::Todo(_)) => {
                        return Ok(subscript_ty);
                    }
                    _ => {}
                }
                return Err(vec![parameters]);
            }
            _ => {
                if !self.in_string_annotation() {
                    self.infer_expression(parameters, TypeContext::default());
                }
                return Err(vec![parameters]);
            }
        };

        Ok(if let Type::LiteralValue(literal) = ty {
            // Avoid promoting values originating from an explicitly annotated literal type.
            Type::LiteralValue(literal.to_unpromotable())
        } else {
            ty
        })
    }

    /// Infer the first argument to a `typing.Callable` type expression and returns the
    /// corresponding [`Parameters`].
    ///
    /// It returns `None` if the argument is invalid i.e., not a list of types, parameter
    /// specification, `typing.Concatenate`, or `...`.
    pub(super) fn infer_callable_parameter_types(
        &mut self,
        parameters: &ast::Expr,
    ) -> Option<Parameters<'db>> {
        match parameters {
            ast::Expr::EllipsisLiteral(ast::ExprEllipsisLiteral { .. }) => {
                return Some(Parameters::gradual_form());
            }
            ast::Expr::List(ast::ExprList { elts: params, .. }) => {
                if let [ast::Expr::EllipsisLiteral(_)] = &params[..] {
                    // Return `None` here so that we emit a specific diagnostic at the callsite.
                    return None;
                }

                let mut parameters = Vec::with_capacity(params.len());

                let previously_in_valid_unpack_context = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::IN_VALID_UNPACK_CONTEXT, true);
                for param in params {
                    let param_type = self.infer_type_expression(param);
                    let is_unpack = self
                        .type_expression_flags(param)
                        .contains(TypeExpressionFlags::UNPACK);

                    if is_unpack {
                        if let Type::TypeVar(typevar) = param_type
                            && typevar.is_typevartuple(self.db())
                        {
                            parameters.push(
                                Parameter::variadic(Name::new_static("args"))
                                    .with_annotated_type(Type::TypeVar(typevar))
                                    .with_starred_annotation(),
                            );
                            continue;
                        }

                        if param_type.exact_tuple_instance_spec(self.db()).is_some() {
                            parameters.push(
                                Parameter::variadic(Name::new_static("args"))
                                    .with_annotated_type(param_type)
                                    .with_starred_annotation(),
                            );
                            continue;
                        }
                    }

                    parameters
                        .push(Parameter::positional_only(None).with_annotated_type(param_type));
                }
                self.context.inference_flags.set(
                    InferenceFlags::IN_VALID_UNPACK_CONTEXT,
                    previously_in_valid_unpack_context,
                );

                return Some(Parameters::from_annotation(self.db(), parameters));
            }
            ast::Expr::Subscript(subscript) => {
                let value_ty = self.infer_expression(&subscript.value, TypeContext::default());

                if matches!(value_ty, Type::SpecialForm(SpecialFormType::Concatenate)) {
                    return Some(self.infer_concatenate_special_form(subscript));
                }

                self.infer_subscript_type_expression(subscript, value_ty);

                // Non-Concatenate subscript (e.g. Unpack): fall back to todo
                return Some(Parameters::todo());
            }
            ast::Expr::Name(_) | ast::Expr::Attribute(_) => {
                if parameters
                    .as_name_expr()
                    .is_some_and(ast::ExprName::is_invalid)
                {
                    // This is a special case to avoid raising the error suggesting what the first
                    // argument should be. This only happens when there's already a syntax error like
                    // `Callable[]`.
                    return None;
                }
                let previously_allowed_paramspec = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR, true);
                let parameters_type = self.infer_type_expression_no_store(parameters);
                self.context.inference_flags.set(
                    InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR,
                    previously_allowed_paramspec,
                );
                if let Type::TypeVar(tvar) = parameters_type
                    && tvar.is_paramspec(self.db())
                {
                    return Some(Parameters::paramspec(self.db(), tvar));
                }
                if parameters_type == Type::Dynamic(DynamicType::InvalidConcatenateUnknown) {
                    // Avoid emitting a confusing error here saying that the first argument to
                    // `Callable` must be "Concatenate, `...`, a parameter list or a ParamSpec"
                    // if the first argument *was* in fact `Concatenate` -- it was just used
                    // incorrectly. We'll have emitted an error elsewhere about the invalid use.
                    return Some(Parameters::unknown());
                }
            }
            ast::Expr::StringLiteral(string) => {
                if let Some(parsed) =
                    parse_string_annotation(&self.context, self.inference_flags(), string)
                {
                    self.string_annotations
                        .insert(ruff_python_ast::ExprRef::StringLiteral(string).into());
                    let node_key = self.enclosing_node_key(string.into());

                    let previous_deferred_state = std::mem::replace(
                        &mut self.deferred_state,
                        DeferredExpressionState::InStringAnnotation(node_key),
                    );
                    let result = matches!(
                        parsed.expr(),
                        ast::Expr::Name(_) | ast::Expr::Attribute(_) | ast::Expr::Subscript(_)
                    )
                    .then(|| self.infer_callable_parameter_types(parsed.expr()));
                    self.deferred_state = previous_deferred_state;

                    if let Some(result) = result {
                        return result;
                    }
                }
            }
            _ => {}
        }
        if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, parameters) {
            let diag = builder.into_diagnostic(format_args!(
                "The first argument to `Callable` must be either a list of types, \
                ParamSpec, Concatenate, or `...`",
            ));
            diagnostic::add_type_expression_reference_link(diag);
        }
        None
    }

    /// Infer the parameter types represented by a `typing.Concatenate` special form.
    pub(super) fn infer_concatenate_special_form(
        &mut self,
        subscript: &ast::ExprSubscript,
    ) -> Parameters<'db> {
        let previous_concatenate_context = self
            .context
            .inference_flags
            .replace(InferenceFlags::IN_VALID_CONCATENATE_CONTEXT, false);

        let arguments_slice = &*subscript.slice;
        let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
            &*tuple.elts
        } else {
            std::slice::from_ref(arguments_slice)
        };

        let (last_arg, prefix_args) = match arguments.split_last() {
            Some((last_arg, prefix_args)) if !prefix_args.is_empty() => (last_arg, prefix_args),
            _ => {
                if !self.in_string_annotation() {
                    for argument in arguments {
                        self.infer_expression(argument, TypeContext::default());
                    }
                }
                if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
                    builder.into_diagnostic(format_args!(
                        "`typing.Concatenate` requires at least 2 arguments when used in a \
                        type expression (got {})",
                        arguments.len()
                    ));
                }
                if arguments_slice.is_tuple_expr() {
                    self.store_expression_type(arguments_slice, Type::unknown());
                }
                return Parameters::gradual_form();
            }
        };

        let previously_allowed_paramspec = self
            .context
            .inference_flags
            .replace(InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR, false);
        let prefix_params = prefix_args
            .iter()
            .map(|arg| {
                Parameter::positional_only(None)
                    .with_annotated_type(self.infer_type_expression(arg))
            })
            .collect();
        self.context.inference_flags.set(
            InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR,
            previously_allowed_paramspec,
        );

        let parameters = self
            .infer_concatenate_tail(last_arg)
            .map(|tail| Parameters::concatenate(self.db(), prefix_params, tail));

        if arguments_slice.is_tuple_expr() {
            // TODO: What type to store for the argument slice in `Concatenate` because
            // `Parameters` is not a `Type` variant?
            self.store_expression_type(arguments_slice, Type::unknown());
        }

        let result = parameters.unwrap_or_else(Parameters::unknown);

        self.context.inference_flags.set(
            InferenceFlags::IN_VALID_CONCATENATE_CONTEXT,
            previous_concatenate_context,
        );
        result
    }

    /// Infer the last argument to a `typing.Concatenate` special form, which can be either `...`
    /// (for gradual typing), a `ParamSpec` type variable, or a string annotation that evaluates to
    /// a `ParamSpec` type variable.
    fn infer_concatenate_tail(&mut self, expr: &ast::Expr) -> Option<ConcatenateTail<'db>> {
        match expr {
            ast::Expr::EllipsisLiteral(_) => Some(ConcatenateTail::Gradual),
            ast::Expr::Name(_) | ast::Expr::Attribute(_) => {
                if expr.as_name_expr().is_some_and(ast::ExprName::is_invalid) {
                    return None;
                }
                let previously_allowed_paramspec = self
                    .context
                    .inference_flags
                    .replace(InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR, true);
                let expr_type = self.infer_type_expression_no_store(expr);
                self.context.inference_flags.set(
                    InferenceFlags::ALLOW_PARAMSPEC_TYPE_EXPR,
                    previously_allowed_paramspec,
                );
                let Type::TypeVar(typevar) = expr_type else {
                    // `Concatenate` *is* allowed inside `Concatenate`, so avoid emitting here a diagnostic
                    // saying that the argument is invalid if the inner type is an invalid use of the
                    // `Concatenate` special form (we'll already have complained about the invalid use
                    // elsewhere)
                    if expr_type != Type::Dynamic(DynamicType::InvalidConcatenateUnknown) {
                        report_invalid_concatenate_last_arg(&self.context, expr, expr_type);
                    }
                    return None;
                };
                if !typevar.is_paramspec(self.db()) {
                    report_invalid_concatenate_last_arg(&self.context, expr, expr_type);
                    return None;
                }
                Some(ConcatenateTail::ParamSpec(typevar))
            }
            ast::Expr::StringLiteral(string) => {
                let Some(parsed) =
                    parse_string_annotation(&self.context, self.inference_flags(), string)
                else {
                    report_invalid_concatenate_last_arg(&self.context, expr, Type::unknown());
                    return None;
                };

                self.string_annotations
                    .insert(ruff_python_ast::ExprRef::StringLiteral(string).into());
                let node_key = self.enclosing_node_key(string.into());

                if !matches!(
                    parsed.expr(),
                    ast::Expr::Name(_) | ast::Expr::Attribute(_) | ast::Expr::Subscript(_)
                ) {
                    report_invalid_concatenate_last_arg(&self.context, expr, Type::unknown());
                    return None;
                }

                let previous_deferred_state = std::mem::replace(
                    &mut self.deferred_state,
                    DeferredExpressionState::InStringAnnotation(node_key),
                );
                let result = self.infer_concatenate_tail(parsed.expr());
                self.deferred_state = previous_deferred_state;

                result
            }
            _ => {
                let ty = self.infer_type_expression(expr);
                if ty != Type::Dynamic(DynamicType::InvalidConcatenateUnknown) {
                    report_invalid_concatenate_last_arg(&self.context, expr, ty);
                }
                None
            }
        }
    }

    /// Checks if the inferred type is an unbound type variable and reports a diagnostic if so.
    ///
    /// Returns `Unknown` as a fallback if the type variable is unbound, otherwise returns the
    /// original type unchanged.
    pub(super) fn check_for_unbound_type_variable(
        &self,
        expression: &ast::Expr,
        ty: Type<'db>,
    ) -> Type<'db> {
        if !self
            .inference_flags()
            .contains(InferenceFlags::CHECK_UNBOUND_TYPEVARS)
        {
            return ty;
        }
        if let Type::KnownInstance(KnownInstanceType::TypeVar(typevar)) = ty {
            if let Some(builder) = self.context.report_lint(&UNBOUND_TYPE_VARIABLE, expression) {
                builder.into_diagnostic(format_args!(
                    "Type variable `{name}` is not bound to any outer generic context",
                    name = typevar.name(self.db())
                ));
            }
            Type::unknown()
        } else {
            ty
        }
    }
}
