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

Code before:
                KnownClass::Mapping
                    .to_specialized_instance(db, [KnownClass::Str.to_instance(db), Type::object()])
                    .has_relation_to_impl(
                        db,
                        target,
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,
                    )
            }),

            // A non-`TypedDict` cannot subtype a `TypedDict`
            (_, Type::TypedDict(_)) => ConstraintSet::from(false),

            // All `StringLiteral` types are a subtype of `LiteralString`.
            (Type::StringLiteral(_), Type::LiteralString) => ConstraintSet::from(true),

            // A string literal `Literal["abc"]` is assignable to `str` *and* to
            // `Sequence[Literal["a", "b", "c"]]` because strings are sequences of their characters.
            //
            // Note that this strictly holds true for all type relations!
            // However, as an optimisation (to avoid interning many single-character string-literal types),
            // we only recognise this as being true for assignability.
            (Type::StringLiteral(value), Type::NominalInstance(instance))
                if relation.is_assignability() =>
            {
                let other_class = instance.class(db);

                if other_class.is_known(db, KnownClass::Str) {
                    return ConstraintSet::from(true);
                }

                let chars: FxHashSet<char> = value.value(db).chars().collect();

                let spec = match chars.len() {
                    0 => Type::Never,
                    1 => Type::StringLiteral(StringLiteralType::new(
                        db,
                        chars.iter().next().unwrap().to_compact_string(),
                    )),
                    _ => {
                        // Optimisation: since we know this union will only include string-literal types,
                        // avoid eagerly creating string-literal types when unnecessary, and avoid going
                        // via the union-builder.
                        let union_elements: Box<[Type<'db>]> = chars
                            .iter()
                            .map(|c| {
                                Type::StringLiteral(StringLiteralType::new(
                                    db,
                                    c.to_compact_string(),

Review comment (suggestion):
I think if we do it for assignability we should probably do it for subtyping as well? For fully static types I think it's important that assignability and subtyping stay equivalent.

I expect that specifically excluding is-redundant-with here would have the same impact, since subtyping is rarely used.

Code after:
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,
                    )
                }),

            // TODO: When we support `closed` and/or `extra_items`, we could allow assignments to other
            // compatible `Mapping`s. `extra_items` could also allow for some assignments to `dict`, as
            // long as `total=False`. (But then again, does anyone want a non-total `TypedDict` where all
            // key types are a supertype of the extra items type?)
            (Type::TypedDict(_), _) => relation_visitor.visit((self, target, relation), || {
                KnownClass::Mapping
                    .to_specialized_instance(db, &[KnownClass::Str.to_instance(db), Type::object()])
                    .has_relation_to_impl(
                        db,
                        target,
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,
                    )
            }),

            // A non-`TypedDict` cannot subtype a `TypedDict`
            (_, Type::TypedDict(_)) => ConstraintSet::from(false),

            // All `StringLiteral` types are a subtype of `LiteralString`.
            (Type::StringLiteral(_), Type::LiteralString) => ConstraintSet::from(true),

            // A string literal `Literal["abc"]` is assignable to `str` *and* to
            // `Sequence[Literal["a", "b", "c"]]` because strings are sequences of their characters.
            //
            // Note that this strictly holds true for all type relations!
            // However, as an optimisation (to avoid interning many single-character string-literal types),
            // we only recognise this as being true for assignability.
            (Type::StringLiteral(value), Type::NominalInstance(instance)) => {
                let other_class = instance.class(db);

                if other_class.is_known(db, KnownClass::Str) {
                    return ConstraintSet::from(true);
                }

                if let Some(sequence_class) = KnownClass::Sequence.try_to_class_literal(db)
                    && !sequence_class
                        .iter_mro(db, None)
                        .filter_map(ClassBase::into_class)
                        .map(|class| class.class_literal(db))
                        .contains(&other_class.class_literal(db))
                {
                    return ConstraintSet::from(false);