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

Code before:
        } else {
            KnownClass::TypedDictFallback
                .to_class_literal(db)
                .find_name_in_mro_with_policy(db, name, policy)
                .expect("`find_name_in_mro_with_policy` will return `Some()` when called on class literal")
                .map_type(|ty|
                    ty.apply_type_mapping(
                        db,
                        &TypeMapping::ReplaceSelf {
                            new_upper_bound: determine_upper_bound(
                                db,
                                self,
                                specialization,
                                ClassBase::is_typed_dict
                            )
                        },
                                TypeContext::default(),
                    )
                )
        }
    }

    /// Returns a list of all annotated attributes defined in this class, or any of its superclasses.
    ///
    /// See [`ClassLiteral::own_fields`] for more details.
    #[salsa::tracked(returns(ref))]
    pub(crate) fn fields(
        self,
        db: &'db dyn Db,
        specialization: Option<Specialization<'db>>,
        field_policy: CodeGeneratorKind<'db>,
    ) -> FxIndexMap<Name, Field<'db>> {
        if field_policy == CodeGeneratorKind::NamedTuple {
            // NamedTuples do not allow multiple inheritance, so it is sufficient to enumerate the
            // fields of this class only.
            return self.own_fields(db, specialization, field_policy);
        }

        let matching_classes_in_mro: Vec<_> = self
            .iter_mro(db, specialization)
            .filter_map(|superclass| {
                if let Some(class) = superclass.into_class() {
                    let (class_literal, specialization) = class.class_literal(db);
                    if field_policy.matches(db, class_literal, specialization) {
                        Some((class_literal, specialization))
                    } else {
                        None
                    }
                } else {
                    None
                }

Review comment (performance):
Seems reasonable to cache this. Can you add the `heap_size` attribute so that we can get a sense of how expensive this is in terms of memory consumption?

How much does it change performance if we were to cache `own_fields` only? I'm asking because that would require slightly less memory

Code after:
        } else {
            KnownClass::TypedDictFallback
                .to_class_literal(db)
                .find_name_in_mro_with_policy(db, name, policy)
                .expect("`find_name_in_mro_with_policy` will return `Some()` when called on class literal")
                .map_type(|ty|
                    ty.apply_type_mapping(
                        db,
                        &TypeMapping::ReplaceSelf {
                            new_upper_bound: determine_upper_bound(
                                db,
                                self,
                                specialization,
                                ClassBase::is_typed_dict
                            )
                        },
                                TypeContext::default(),
                    )
                )
        }
    }

    /// Returns a list of all annotated attributes defined in this class, or any of its superclasses.
    ///
    /// See [`ClassLiteral::own_fields`] for more details.
    #[salsa::tracked(returns(ref), heap_size=get_size2::GetSize::get_heap_size)]
    pub(crate) fn fields(
        self,
        db: &'db dyn Db,
        specialization: Option<Specialization<'db>>,
        field_policy: CodeGeneratorKind<'db>,
    ) -> FxIndexMap<Name, Field<'db>> {
        if field_policy == CodeGeneratorKind::NamedTuple {
            // NamedTuples do not allow multiple inheritance, so it is sufficient to enumerate the
            // fields of this class only.
            return self.own_fields(db, specialization, field_policy);
        }

        let matching_classes_in_mro: Vec<_> = self
            .iter_mro(db, specialization)
            .filter_map(|superclass| {
                if let Some(class) = superclass.into_class() {
                    let (class_literal, specialization) = class.class_literal(db);
                    if field_policy.matches(db, class_literal, specialization) {
                        Some((class_literal, specialization))
                    } else {
                        None
                    }
                } else {
                    None
                }