From 6d8f2864c354874d75c32c3df6c24c8f88025152 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 13 Jan 2026 08:53:49 -0500 Subject: [PATCH] [ty] Rename MRO structs to match static nomenclature (#22549) ## Summary I didn't want to make the "dynamic" `type(...)` PR any larger, but it probably makes sense to rename these now that we have `Dynamic` variants. --- crates/ty_python_semantic/src/types.rs | 2 +- crates/ty_python_semantic/src/types/class.rs | 10 ++-- .../src/types/class_base.rs | 4 +- .../src/types/infer/builder.rs | 12 ++-- crates/ty_python_semantic/src/types/mro.rs | 58 +++++++++++-------- 5 files changed, 48 insertions(+), 38 deletions(-) diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 76cc4684b1..e923c4df48 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -64,7 +64,7 @@ use crate::types::generics::{ ApplySpecialization, InferableTypeVars, Specialization, SpecializationBuilder, bind_typevar, typing_self, walk_generic_context, }; -use crate::types::mro::{Mro, MroError, MroIterator}; +use crate::types::mro::{Mro, MroIterator, StaticMroError}; pub(crate) use crate::types::narrow::{NarrowingConstraint, infer_narrowing_constraint}; use crate::types::newtype::NewType; pub(crate) use crate::types::signatures::{Parameter, Parameters}; diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index ba4f3b61fc..3287503d87 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -5,7 +5,7 @@ use std::sync::{LazyLock, Mutex}; use super::TypeVarVariance; use super::{ - BoundTypeVarInstance, MemberLookupPolicy, Mro, MroError, MroIterator, SpecialFormType, + BoundTypeVarInstance, MemberLookupPolicy, Mro, MroIterator, SpecialFormType, StaticMroError, SubclassOfType, Truthiness, Type, TypeQualifiers, class_base::ClassBase, function::FunctionType, }; @@ -128,8 +128,8 @@ fn try_mro_cycle_initial<'db>( _id: salsa::Id, self_: StaticClassLiteral<'db>, specialization: Option>, -) -> Result, MroError<'db>> { - Err(MroError::cycle( +) -> Result, StaticMroError<'db>> { + Err(StaticMroError::cycle( db, self_.apply_optional_specialization(db, specialization), )) @@ -2498,7 +2498,7 @@ impl<'db> StaticClassLiteral<'db> { self, db: &'db dyn Db, specialization: Option>, - ) -> Result, MroError<'db>> { + ) -> Result, StaticMroError<'db>> { tracing::trace!("StaticClassLiteral::try_mro: {}", self.name(db)); Mro::of_static_class(db, self, specialization) } @@ -2605,7 +2605,7 @@ impl<'db> StaticClassLiteral<'db> { return Ok((SubclassOfType::subclass_of_unknown(), None)); } - if self.try_mro(db, None).is_err_and(MroError::is_cycle) { + if self.try_mro(db, None).is_err_and(StaticMroError::is_cycle) { return Ok((SubclassOfType::subclass_of_unknown(), None)); } diff --git a/crates/ty_python_semantic/src/types/class_base.rs b/crates/ty_python_semantic/src/types/class_base.rs index 6d644fea5f..a6c428a58e 100644 --- a/crates/ty_python_semantic/src/types/class_base.rs +++ b/crates/ty_python_semantic/src/types/class_base.rs @@ -6,7 +6,7 @@ use crate::types::mro::MroIterator; use crate::types::tuple::TupleType; use crate::types::{ ApplyTypeMappingVisitor, ClassLiteral, ClassType, DynamicType, KnownClass, KnownInstanceType, - MaterializationKind, MroError, NormalizedVisitor, SpecialFormType, Type, TypeContext, + MaterializationKind, NormalizedVisitor, SpecialFormType, StaticMroError, Type, TypeContext, TypeMapping, todo_type, }; @@ -381,7 +381,7 @@ impl<'db> ClassBase<'db> { }; class_literal .try_mro(db, specialization) - .is_err_and(MroError::is_cycle) + .is_err_and(StaticMroError::is_cycle) } ClassBase::Dynamic(_) | ClassBase::Generic diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index 4332542b81..60e4fb2fff 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -102,7 +102,7 @@ use crate::types::generics::{ }; use crate::types::infer::nearest_enclosing_function; use crate::types::instance::SliceLiteral; -use crate::types::mro::{DynamicMroErrorKind, MroErrorKind}; +use crate::types::mro::{DynamicMroErrorKind, StaticMroErrorKind}; use crate::types::newtype::NewType; use crate::types::subclass_of::SubclassOfInner; use crate::types::tuple::{Tuple, TupleLength, TupleSpec, TupleType}; @@ -797,13 +797,13 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { // (4) Check that the class's MRO is resolvable match class.try_mro(self.db(), None) { Err(mro_error) => match mro_error.reason() { - MroErrorKind::DuplicateBases(duplicates) => { + StaticMroErrorKind::DuplicateBases(duplicates) => { let base_nodes = class_node.bases(); for duplicate in duplicates { report_duplicate_bases(&self.context, class, duplicate, base_nodes); } } - MroErrorKind::InvalidBases(bases) => { + StaticMroErrorKind::InvalidBases(bases) => { let base_nodes = class_node.bases(); for (index, base_ty) in bases { report_invalid_or_unsupported_base( @@ -814,7 +814,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { ); } } - MroErrorKind::UnresolvableMro { bases_list } => { + StaticMroErrorKind::UnresolvableMro { bases_list } => { if let Some(builder) = self.context.report_lint(&INCONSISTENT_MRO, class_node) { @@ -829,7 +829,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { )); } } - MroErrorKind::Pep695ClassWithGenericInheritance => { + StaticMroErrorKind::Pep695ClassWithGenericInheritance => { if let Some(builder) = self.context.report_lint(&INVALID_GENERIC_CLASS, class_node) { @@ -839,7 +839,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { ); } } - MroErrorKind::InheritanceCycle => { + StaticMroErrorKind::InheritanceCycle => { if let Some(builder) = self .context .report_lint(&CYCLIC_CLASS_DEFINITION, class_node) diff --git a/crates/ty_python_semantic/src/types/mro.rs b/crates/ty_python_semantic/src/types/mro.rs index 82430a0e8a..5af9b20a90 100644 --- a/crates/ty_python_semantic/src/types/mro.rs +++ b/crates/ty_python_semantic/src/types/mro.rs @@ -53,7 +53,7 @@ impl<'db> Mro<'db> { db: &'db dyn Db, class_literal: StaticClassLiteral<'db>, specialization: Option>, - ) -> Result> { + ) -> Result> { /// Possibly add `Generic` to the resolved bases list. /// /// This function is called in two cases: @@ -141,10 +141,15 @@ impl<'db> Mro<'db> { { ClassBase::try_from_type(db, *single_base, ClassLiteral::Static(class_literal)) .map_or_else( - || Err(MroErrorKind::InvalidBases(Box::from([(0, *single_base)]))), + || { + Err(StaticMroErrorKind::InvalidBases(Box::from([( + 0, + *single_base, + )]))) + }, |single_base| { if single_base.has_cyclic_mro(db) { - Err(MroErrorKind::InheritanceCycle) + Err(StaticMroErrorKind::InheritanceCycle) } else { Ok(std::iter::once(ClassBase::Class(class)) .chain(single_base.mro(db, specialization)) @@ -188,8 +193,10 @@ impl<'db> Mro<'db> { } if !invalid_bases.is_empty() { - return Err(MroErrorKind::InvalidBases(invalid_bases.into_boxed_slice()) - .into_mro_error(db, class)); + return Err( + StaticMroErrorKind::InvalidBases(invalid_bases.into_boxed_slice()) + .into_mro_error(db, class), + ); } // `Generic` is implicitly added to the bases list of a class that has PEP-695 type parameters @@ -201,7 +208,7 @@ impl<'db> Mro<'db> { let mut seqs = vec![VecDeque::from([ClassBase::Class(class)])]; for base in &resolved_bases { if base.has_cyclic_mro(db) { - return Err(MroErrorKind::InheritanceCycle.into_mro_error(db, class)); + return Err(StaticMroErrorKind::InheritanceCycle.into_mro_error(db, class)); } seqs.push(base.mro(db, specialization).collect()); } @@ -229,9 +236,8 @@ impl<'db> Mro<'db> { ) }) { - return Err( - MroErrorKind::Pep695ClassWithGenericInheritance.into_mro_error(db, class) - ); + return Err(StaticMroErrorKind::Pep695ClassWithGenericInheritance + .into_mro_error(db, class)); } let mut duplicate_dynamic_bases = false; @@ -291,14 +297,14 @@ impl<'db> Mro<'db> { if duplicate_dynamic_bases { Ok(Mro::from_error(db, class)) } else { - Err(MroErrorKind::UnresolvableMro { + Err(StaticMroErrorKind::UnresolvableMro { bases_list: original_bases.iter().copied().collect(), } .into_mro_error(db, class)) } } else { Err( - MroErrorKind::DuplicateBases(duplicate_bases.into_boxed_slice()) + StaticMroErrorKind::DuplicateBases(duplicate_bases.into_boxed_slice()) .into_mro_error(db, class), ) } @@ -537,23 +543,23 @@ impl<'db> Iterator for MroIterator<'db> { impl std::iter::FusedIterator for MroIterator<'_> {} #[derive(Debug, PartialEq, Eq, salsa::Update, get_size2::GetSize)] -pub(super) struct MroError<'db> { - kind: MroErrorKind<'db>, +pub(super) struct StaticMroError<'db> { + kind: StaticMroErrorKind<'db>, fallback_mro: Mro<'db>, } -impl<'db> MroError<'db> { +impl<'db> StaticMroError<'db> { /// Construct an MRO error of kind `InheritanceCycle`. pub(super) fn cycle(db: &'db dyn Db, class: ClassType<'db>) -> Self { - MroErrorKind::InheritanceCycle.into_mro_error(db, class) + StaticMroErrorKind::InheritanceCycle.into_mro_error(db, class) } pub(super) fn is_cycle(&self) -> bool { - matches!(self.kind, MroErrorKind::InheritanceCycle) + matches!(self.kind, StaticMroErrorKind::InheritanceCycle) } - /// Return an [`MroErrorKind`] variant describing why we could not resolve the MRO for this class. - pub(super) fn reason(&self) -> &MroErrorKind<'db> { + /// Return an [`StaticMroErrorKind`] variant describing why we could not resolve the MRO for this class. + pub(super) fn reason(&self) -> &StaticMroErrorKind<'db> { &self.kind } @@ -564,9 +570,9 @@ impl<'db> MroError<'db> { } } -/// Possible ways in which attempting to resolve the MRO of a class might fail. +/// Possible ways in which attempting to resolve the MRO of a statically-defined class might fail. #[derive(Debug, PartialEq, Eq, salsa::Update, get_size2::GetSize)] -pub(super) enum MroErrorKind<'db> { +pub(super) enum StaticMroErrorKind<'db> { /// The class inherits from one or more invalid bases. /// /// To avoid excessive complexity in our implementation, @@ -596,9 +602,13 @@ pub(super) enum MroErrorKind<'db> { UnresolvableMro { bases_list: Box<[Type<'db>]> }, } -impl<'db> MroErrorKind<'db> { - pub(super) fn into_mro_error(self, db: &'db dyn Db, class: ClassType<'db>) -> MroError<'db> { - MroError { +impl<'db> StaticMroErrorKind<'db> { + pub(super) fn into_mro_error( + self, + db: &'db dyn Db, + class: ClassType<'db>, + ) -> StaticMroError<'db> { + StaticMroError { kind: self, fallback_mro: Mro::from_error(db, class), } @@ -660,7 +670,7 @@ fn c3_merge(mut sequences: Vec>) -> Option { /// Error for dynamic class MRO computation with fallback MRO. /// -/// Separate from [`MroError`] because dynamic classes can only have a subset of MRO errors. +/// Separate from [`StaticMroError`] because dynamic classes can only have a subset of MRO errors. #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize, salsa::Update)] pub(crate) struct DynamicMroError<'db> { kind: DynamicMroErrorKind<'db>,