Compare commits

...

3 Commits

Author SHA1 Message Date
David Peter
6e83ce9e5d Address review comments 2025-05-14 20:24:11 +02:00
David Peter
d998bea5de Fix violated invariant 2025-05-14 20:24:11 +02:00
David Peter
3a76557be2 [ty] Deterministic ordering of types 2025-05-14 20:24:11 +02:00
7 changed files with 180 additions and 33 deletions

View File

@@ -149,6 +149,14 @@ impl<'db> ScopeId<'db> {
NodeWithScopeKind::GeneratorExpression(_) => "<generator>", NodeWithScopeKind::GeneratorExpression(_) => "<generator>",
} }
} }
pub(crate) fn ordering(self, db: &'db dyn Db, other: Self) -> std::cmp::Ordering {
self.file(db)
.path(db)
.as_str()
.cmp(other.file(db).path(db).as_str())
.then_with(|| self.file_scope_id(db).0.cmp(&other.file_scope_id(db).0))
}
} }
/// ID that uniquely identifies a scope inside of a module. /// ID that uniquely identifies a scope inside of a module.

View File

@@ -1,6 +1,7 @@
use infer::enclosing_class_symbol; use infer::enclosing_class_symbol;
use itertools::Either; use itertools::Either;
use std::cmp::Ordering;
use std::slice::Iter; use std::slice::Iter;
use std::str::FromStr; use std::str::FromStr;
@@ -7973,6 +7974,10 @@ impl<'db> StringLiteralType<'db> {
.chars() .chars()
.map(|c| StringLiteralType::new(db, c.to_string().as_str())) .map(|c| StringLiteralType::new(db, c.to_string().as_str()))
} }
pub(crate) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.value(db).cmp(other.value(db))
}
} }
#[salsa::interned(debug)] #[salsa::interned(debug)]
@@ -7985,6 +7990,10 @@ impl<'db> BytesLiteralType<'db> {
pub(crate) fn python_len(self, db: &'db dyn Db) -> usize { pub(crate) fn python_len(self, db: &'db dyn Db) -> usize {
self.value(db).len() self.value(db).len()
} }
pub(crate) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.value(db).cmp(other.value(db))
}
} }
#[salsa::interned(debug)] #[salsa::interned(debug)]

View File

@@ -1,3 +1,4 @@
use std::cmp::Ordering;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use std::sync::{LazyLock, Mutex}; use std::sync::{LazyLock, Mutex};
@@ -187,6 +188,15 @@ impl<'db> GenericAlias<'db> {
) { ) {
self.specialization(db).find_legacy_typevars(db, typevars); self.specialization(db).find_legacy_typevars(db, typevars);
} }
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.origin(db)
.ordering(db, other.origin(db))
.then_with(|| {
self.specialization(db)
.ordering(db, other.specialization(db))
})
}
} }
impl<'db> From<GenericAlias<'db>> for Type<'db> { impl<'db> From<GenericAlias<'db>> for Type<'db> {
@@ -197,9 +207,7 @@ impl<'db> From<GenericAlias<'db>> for Type<'db> {
/// Represents a class type, which might be a non-generic class, or a specialization of a generic /// Represents a class type, which might be a non-generic class, or a specialization of a generic
/// class. /// class.
#[derive( #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Supertype, salsa::Update)]
Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Supertype, salsa::Update,
)]
pub enum ClassType<'db> { pub enum ClassType<'db> {
NonGeneric(ClassLiteral<'db>), NonGeneric(ClassLiteral<'db>),
Generic(GenericAlias<'db>), Generic(GenericAlias<'db>),
@@ -470,6 +478,15 @@ impl<'db> ClassType<'db> {
.own_instance_member(db, name) .own_instance_member(db, name)
.map_type(|ty| ty.apply_optional_specialization(db, specialization)) .map_type(|ty| ty.apply_optional_specialization(db, specialization))
} }
pub fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
match (self, other) {
(ClassType::NonGeneric(_), ClassType::Generic(_)) => Ordering::Less,
(ClassType::Generic(_), ClassType::NonGeneric(_)) => Ordering::Greater,
(ClassType::NonGeneric(this), ClassType::NonGeneric(other)) => this.ordering(db, other),
(ClassType::Generic(this), ClassType::Generic(other)) => this.ordering(db, other),
}
}
} }
impl<'db> From<GenericAlias<'db>> for ClassType<'db> { impl<'db> From<GenericAlias<'db>> for ClassType<'db> {
@@ -506,6 +523,14 @@ pub struct ClassLiteral<'db> {
pub(crate) dataclass_transformer_params: Option<DataclassTransformerParams>, pub(crate) dataclass_transformer_params: Option<DataclassTransformerParams>,
} }
impl<'db> ClassLiteral<'db> {
pub fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.name(db)
.cmp(other.name(db))
.then_with(|| self.body_scope(db).ordering(db, other.body_scope(db)))
}
}
#[expect(clippy::trivially_copy_pass_by_ref, clippy::ref_option)] #[expect(clippy::trivially_copy_pass_by_ref, clippy::ref_option)]
fn pep695_generic_context_cycle_recover<'db>( fn pep695_generic_context_cycle_recover<'db>(
_db: &'db dyn Db, _db: &'db dyn Db,

View File

@@ -1,3 +1,5 @@
use std::cmp::Ordering;
use ruff_python_ast as ast; use ruff_python_ast as ast;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@@ -7,8 +9,9 @@ use crate::types::class_base::ClassBase;
use crate::types::instance::{NominalInstanceType, Protocol, ProtocolInstanceType}; use crate::types::instance::{NominalInstanceType, Protocol, ProtocolInstanceType};
use crate::types::signatures::{Parameter, Parameters, Signature}; use crate::types::signatures::{Parameter, Parameters, Signature};
use crate::types::{ use crate::types::{
declaration_type, todo_type, KnownInstanceType, Type, TypeVarBoundOrConstraints, declaration_type, todo_type, type_ordering::union_or_intersection_elements_ordering,
TypeVarInstance, TypeVarVariance, UnionType, KnownInstanceType, Type, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
UnionType,
}; };
use crate::{Db, FxOrderSet}; use crate::{Db, FxOrderSet};
@@ -229,9 +232,15 @@ impl<'db> GenericContext<'db> {
Specialization::new(db, self, expanded.into_boxed_slice()) Specialization::new(db, self, expanded.into_boxed_slice())
} }
pub(crate) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.variables(db)
.cmp(other.variables(db))
.then_with(|| self.origin(db).cmp(&other.origin(db)))
}
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub enum GenericContextOrigin { pub enum GenericContextOrigin {
LegacyBase(LegacyGenericBase), LegacyBase(LegacyGenericBase),
Inherited, Inherited,
@@ -256,7 +265,7 @@ impl std::fmt::Display for GenericContextOrigin {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub enum LegacyGenericBase { pub enum LegacyGenericBase {
Generic, Generic,
Protocol, Protocol,
@@ -518,6 +527,29 @@ impl<'db> Specialization<'db> {
ty.find_legacy_typevars(db, typevars); ty.find_legacy_typevars(db, typevars);
} }
} }
pub(crate) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.generic_context(db)
.ordering(db, other.generic_context(db))
.then_with(|| {
let self_types = self.types(db);
let other_types = other.types(db);
self_types.len().cmp(&other_types.len()).then_with(|| {
self.types(db)
.iter()
.zip(other.types(db))
.map(|(self_type, other_type)| {
union_or_intersection_elements_ordering(
db,
&self_type.normalized(db),
&other_type.normalized(db),
)
})
.fold(Ordering::Equal, Ordering::then)
})
})
}
} }
/// A mapping between type variables and types. /// A mapping between type variables and types.

View File

@@ -1,5 +1,6 @@
//! Instance types: both nominal and structural. //! Instance types: both nominal and structural.
use std::cmp::Ordering;
use std::marker::PhantomData; use std::marker::PhantomData;
use super::protocol_class::ProtocolInterface; use super::protocol_class::ProtocolInterface;
@@ -157,7 +158,7 @@ impl<'db> From<NominalInstanceType<'db>> for Type<'db> {
/// A `ProtocolInstanceType` represents the set of all possible runtime objects /// A `ProtocolInstanceType` represents the set of all possible runtime objects
/// that conform to the interface described by a certain protocol. /// that conform to the interface described by a certain protocol.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, salsa::Update)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
pub struct ProtocolInstanceType<'db> { pub struct ProtocolInstanceType<'db> {
pub(super) inner: Protocol<'db>, pub(super) inner: Protocol<'db>,
@@ -330,11 +331,15 @@ impl<'db> ProtocolInstanceType<'db> {
} }
} }
} }
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.inner.ordering(db, other.inner)
}
} }
/// An enumeration of the two kinds of protocol types: those that originate from a class /// An enumeration of the two kinds of protocol types: those that originate from a class
/// definition in source code, and those that are synthesized from a set of members. /// definition in source code, and those that are synthesized from a set of members.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update, PartialOrd, Ord)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
pub(super) enum Protocol<'db> { pub(super) enum Protocol<'db> {
FromClass(ClassType<'db>), FromClass(ClassType<'db>),
Synthesized(SynthesizedProtocolType<'db>), Synthesized(SynthesizedProtocolType<'db>),
@@ -353,9 +358,20 @@ impl<'db> Protocol<'db> {
Self::Synthesized(synthesized) => synthesized.interface(), Self::Synthesized(synthesized) => synthesized.interface(),
} }
} }
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
match (self, other) {
(Self::FromClass(_), Self::Synthesized(_)) => Ordering::Greater,
(Self::Synthesized(_), Self::FromClass(_)) => Ordering::Less,
(Self::FromClass(this), Self::FromClass(other)) => this.ordering(db, other),
(Self::Synthesized(this), Self::Synthesized(other)) => this.ordering(db, other),
}
}
} }
mod synthesized_protocol { mod synthesized_protocol {
use std::cmp::Ordering;
use crate::types::generics::TypeMapping; use crate::types::generics::TypeMapping;
use crate::types::protocol_class::ProtocolInterface; use crate::types::protocol_class::ProtocolInterface;
use crate::types::TypeVarInstance; use crate::types::TypeVarInstance;
@@ -370,7 +386,7 @@ mod synthesized_protocol {
/// ///
/// The constructor method of this type maintains the invariant that a synthesized protocol type /// The constructor method of this type maintains the invariant that a synthesized protocol type
/// is always constructed from a *normalized* protocol interface. /// is always constructed from a *normalized* protocol interface.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update, PartialOrd, Ord)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
pub(in crate::types) struct SynthesizedProtocolType<'db>(ProtocolInterface<'db>); pub(in crate::types) struct SynthesizedProtocolType<'db>(ProtocolInterface<'db>);
impl<'db> SynthesizedProtocolType<'db> { impl<'db> SynthesizedProtocolType<'db> {
@@ -397,5 +413,9 @@ mod synthesized_protocol {
pub(in crate::types) fn interface(self) -> ProtocolInterface<'db> { pub(in crate::types) fn interface(self) -> ProtocolInterface<'db> {
self.0 self.0
} }
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
self.0.ordering(db, other.0)
}
} }
} }

View File

@@ -1,4 +1,4 @@
use std::{collections::BTreeMap, ops::Deref}; use std::{cmp::Ordering, collections::BTreeMap, ops::Deref};
use itertools::{Either, Itertools}; use itertools::{Either, Itertools};
@@ -65,7 +65,7 @@ pub(super) struct ProtocolInterfaceMembers<'db> {
} }
/// The interface of a protocol: the members of that protocol, and the types of those members. /// The interface of a protocol: the members of that protocol, and the types of those members.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update, PartialOrd, Ord)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
pub(super) enum ProtocolInterface<'db> { pub(super) enum ProtocolInterface<'db> {
Members(ProtocolInterfaceMembers<'db>), Members(ProtocolInterfaceMembers<'db>),
SelfReference, SelfReference,
@@ -205,6 +205,17 @@ impl<'db> ProtocolInterface<'db> {
Self::SelfReference => {} Self::SelfReference => {}
} }
} }
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
match (self, other) {
(Self::Members(this), Self::Members(other)) => {
this.inner(db).keys().cmp(other.inner(db).keys())
}
(Self::SelfReference, Self::Members(_)) => Ordering::Less,
(Self::Members(_), Self::SelfReference) => Ordering::Greater,
(Self::SelfReference, Self::SelfReference) => Ordering::Equal,
}
}
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash, salsa::Update)] #[derive(Debug, PartialEq, Eq, Clone, Hash, salsa::Update)]

View File

@@ -56,23 +56,32 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::IntLiteral(_), _) => Ordering::Less, (Type::IntLiteral(_), _) => Ordering::Less,
(_, Type::IntLiteral(_)) => Ordering::Greater, (_, Type::IntLiteral(_)) => Ordering::Greater,
(Type::StringLiteral(left), Type::StringLiteral(right)) => left.cmp(right), (Type::StringLiteral(left), Type::StringLiteral(right)) => left.ordering(db, *right),
(Type::StringLiteral(_), _) => Ordering::Less, (Type::StringLiteral(_), _) => Ordering::Less,
(_, Type::StringLiteral(_)) => Ordering::Greater, (_, Type::StringLiteral(_)) => Ordering::Greater,
(Type::BytesLiteral(left), Type::BytesLiteral(right)) => left.cmp(right), (Type::BytesLiteral(left), Type::BytesLiteral(right)) => left.ordering(db, *right),
(Type::BytesLiteral(_), _) => Ordering::Less, (Type::BytesLiteral(_), _) => Ordering::Less,
(_, Type::BytesLiteral(_)) => Ordering::Greater, (_, Type::BytesLiteral(_)) => Ordering::Greater,
(Type::FunctionLiteral(left), Type::FunctionLiteral(right)) => left.cmp(right), (Type::FunctionLiteral(left), Type::FunctionLiteral(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::FunctionLiteral(_), _) => Ordering::Less, (Type::FunctionLiteral(_), _) => Ordering::Less,
(_, Type::FunctionLiteral(_)) => Ordering::Greater, (_, Type::FunctionLiteral(_)) => Ordering::Greater,
(Type::BoundMethod(left), Type::BoundMethod(right)) => left.cmp(right), (Type::BoundMethod(left), Type::BoundMethod(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::BoundMethod(_), _) => Ordering::Less, (Type::BoundMethod(_), _) => Ordering::Less,
(_, Type::BoundMethod(_)) => Ordering::Greater, (_, Type::BoundMethod(_)) => Ordering::Greater,
(Type::MethodWrapper(left), Type::MethodWrapper(right)) => left.cmp(right), (Type::MethodWrapper(left), Type::MethodWrapper(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::MethodWrapper(_), _) => Ordering::Less, (Type::MethodWrapper(_), _) => Ordering::Less,
(_, Type::MethodWrapper(_)) => Ordering::Greater, (_, Type::MethodWrapper(_)) => Ordering::Greater,
@@ -92,29 +101,40 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::DataclassTransformer(_), _) => Ordering::Less, (Type::DataclassTransformer(_), _) => Ordering::Less,
(_, Type::DataclassTransformer(_)) => Ordering::Greater, (_, Type::DataclassTransformer(_)) => Ordering::Greater,
(Type::Callable(left), Type::Callable(right)) => left.cmp(right), (Type::Callable(left), Type::Callable(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::Callable(_), _) => Ordering::Less, (Type::Callable(_), _) => Ordering::Less,
(_, Type::Callable(_)) => Ordering::Greater, (_, Type::Callable(_)) => Ordering::Greater,
(Type::Tuple(left), Type::Tuple(right)) => left.cmp(right), (Type::Tuple(left), Type::Tuple(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::Tuple(_), _) => Ordering::Less, (Type::Tuple(_), _) => Ordering::Less,
(_, Type::Tuple(_)) => Ordering::Greater, (_, Type::Tuple(_)) => Ordering::Greater,
(Type::ModuleLiteral(left), Type::ModuleLiteral(right)) => left.cmp(right), (Type::ModuleLiteral(left), Type::ModuleLiteral(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::ModuleLiteral(_), _) => Ordering::Less, (Type::ModuleLiteral(_), _) => Ordering::Less,
(_, Type::ModuleLiteral(_)) => Ordering::Greater, (_, Type::ModuleLiteral(_)) => Ordering::Greater,
(Type::ClassLiteral(left), Type::ClassLiteral(right)) => left.cmp(right), (Type::ClassLiteral(left), Type::ClassLiteral(right)) => left.ordering(db, *right),
(Type::ClassLiteral(_), _) => Ordering::Less, (Type::ClassLiteral(_), _) => Ordering::Less,
(_, Type::ClassLiteral(_)) => Ordering::Greater, (_, Type::ClassLiteral(_)) => Ordering::Greater,
(Type::GenericAlias(left), Type::GenericAlias(right)) => left.cmp(right), (Type::GenericAlias(left), Type::GenericAlias(right)) => left.ordering(db, *right),
(Type::GenericAlias(_), _) => Ordering::Less, (Type::GenericAlias(_), _) => Ordering::Less,
(_, Type::GenericAlias(_)) => Ordering::Greater, (_, Type::GenericAlias(_)) => Ordering::Greater,
(Type::SubclassOf(left), Type::SubclassOf(right)) => { (Type::SubclassOf(left), Type::SubclassOf(right)) => {
match (left.subclass_of(), right.subclass_of()) { match (left.subclass_of(), right.subclass_of()) {
(SubclassOfInner::Class(left), SubclassOfInner::Class(right)) => left.cmp(&right), (SubclassOfInner::Class(left), SubclassOfInner::Class(right)) => {
left.ordering(db, right)
}
(SubclassOfInner::Class(_), _) => Ordering::Less, (SubclassOfInner::Class(_), _) => Ordering::Less,
(_, SubclassOfInner::Class(_)) => Ordering::Greater, (_, SubclassOfInner::Class(_)) => Ordering::Greater,
(SubclassOfInner::Dynamic(left), SubclassOfInner::Dynamic(right)) => { (SubclassOfInner::Dynamic(left), SubclassOfInner::Dynamic(right)) => {
@@ -126,17 +146,22 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::SubclassOf(_), _) => Ordering::Less, (Type::SubclassOf(_), _) => Ordering::Less,
(_, Type::SubclassOf(_)) => Ordering::Greater, (_, Type::SubclassOf(_)) => Ordering::Greater,
(Type::NominalInstance(left), Type::NominalInstance(right)) => left.class.cmp(&right.class), (Type::NominalInstance(left), Type::NominalInstance(right)) => {
left.class.ordering(db, right.class)
}
(Type::NominalInstance(_), _) => Ordering::Less, (Type::NominalInstance(_), _) => Ordering::Less,
(_, Type::NominalInstance(_)) => Ordering::Greater, (_, Type::NominalInstance(_)) => Ordering::Greater,
(Type::ProtocolInstance(left_proto), Type::ProtocolInstance(right_proto)) => { (Type::ProtocolInstance(left_proto), Type::ProtocolInstance(right_proto)) => {
left_proto.cmp(right_proto) left_proto.ordering(db, *right_proto)
} }
(Type::ProtocolInstance(_), _) => Ordering::Less, (Type::ProtocolInstance(_), _) => Ordering::Less,
(_, Type::ProtocolInstance(_)) => Ordering::Greater, (_, Type::ProtocolInstance(_)) => Ordering::Greater,
(Type::TypeVar(left), Type::TypeVar(right)) => left.cmp(right), (Type::TypeVar(left), Type::TypeVar(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::TypeVar(_), _) => Ordering::Less, (Type::TypeVar(_), _) => Ordering::Less,
(_, Type::TypeVar(_)) => Ordering::Greater, (_, Type::TypeVar(_)) => Ordering::Greater,
@@ -148,15 +173,21 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::BoundSuper(left), Type::BoundSuper(right)) => { (Type::BoundSuper(left), Type::BoundSuper(right)) => {
(match (left.pivot_class(db), right.pivot_class(db)) { (match (left.pivot_class(db), right.pivot_class(db)) {
(ClassBase::Class(left), ClassBase::Class(right)) => left.cmp(&right), (ClassBase::Class(left), ClassBase::Class(right)) => left.ordering(db, right),
(ClassBase::Class(_), _) => Ordering::Less, (ClassBase::Class(_), _) => Ordering::Less,
(_, ClassBase::Class(_)) => Ordering::Greater, (_, ClassBase::Class(_)) => Ordering::Greater,
(ClassBase::Protocol(left), ClassBase::Protocol(right)) => left.cmp(&right), (ClassBase::Protocol(left), ClassBase::Protocol(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(&right)
}
(ClassBase::Protocol(_), _) => Ordering::Less, (ClassBase::Protocol(_), _) => Ordering::Less,
(_, ClassBase::Protocol(_)) => Ordering::Greater, (_, ClassBase::Protocol(_)) => Ordering::Greater,
(ClassBase::Generic(left), ClassBase::Generic(right)) => left.cmp(&right), (ClassBase::Generic(left), ClassBase::Generic(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(&right)
}
(ClassBase::Generic(_), _) => Ordering::Less, (ClassBase::Generic(_), _) => Ordering::Less,
(_, ClassBase::Generic(_)) => Ordering::Greater, (_, ClassBase::Generic(_)) => Ordering::Greater,
@@ -165,11 +196,13 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
} }
}) })
.then_with(|| match (left.owner(db), right.owner(db)) { .then_with(|| match (left.owner(db), right.owner(db)) {
(SuperOwnerKind::Class(left), SuperOwnerKind::Class(right)) => left.cmp(&right), (SuperOwnerKind::Class(left), SuperOwnerKind::Class(right)) => {
left.ordering(db, right)
}
(SuperOwnerKind::Class(_), _) => Ordering::Less, (SuperOwnerKind::Class(_), _) => Ordering::Less,
(_, SuperOwnerKind::Class(_)) => Ordering::Greater, (_, SuperOwnerKind::Class(_)) => Ordering::Greater,
(SuperOwnerKind::Instance(left), SuperOwnerKind::Instance(right)) => { (SuperOwnerKind::Instance(left), SuperOwnerKind::Instance(right)) => {
left.class.cmp(&right.class) left.class.ordering(db, right.class)
} }
(SuperOwnerKind::Instance(_), _) => Ordering::Less, (SuperOwnerKind::Instance(_), _) => Ordering::Less,
(_, SuperOwnerKind::Instance(_)) => Ordering::Greater, (_, SuperOwnerKind::Instance(_)) => Ordering::Greater,
@@ -247,12 +280,14 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(_, KnownInstanceType::OrderedDict) => Ordering::Greater, (_, KnownInstanceType::OrderedDict) => Ordering::Greater,
(KnownInstanceType::Generic(left), KnownInstanceType::Generic(right)) => { (KnownInstanceType::Generic(left), KnownInstanceType::Generic(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right) left.cmp(right)
} }
(KnownInstanceType::Generic(_), _) => Ordering::Less, (KnownInstanceType::Generic(_), _) => Ordering::Less,
(_, KnownInstanceType::Generic(_)) => Ordering::Greater, (_, KnownInstanceType::Generic(_)) => Ordering::Greater,
(KnownInstanceType::Protocol(left), KnownInstanceType::Protocol(right)) => { (KnownInstanceType::Protocol(left), KnownInstanceType::Protocol(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right) left.cmp(right)
} }
(KnownInstanceType::Protocol(_), _) => Ordering::Less, (KnownInstanceType::Protocol(_), _) => Ordering::Less,
@@ -312,11 +347,15 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
( (
KnownInstanceType::TypeAliasType(left), KnownInstanceType::TypeAliasType(left),
KnownInstanceType::TypeAliasType(right), KnownInstanceType::TypeAliasType(right),
) => left.cmp(right), ) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(KnownInstanceType::TypeAliasType(_), _) => Ordering::Less, (KnownInstanceType::TypeAliasType(_), _) => Ordering::Less,
(_, KnownInstanceType::TypeAliasType(_)) => Ordering::Greater, (_, KnownInstanceType::TypeAliasType(_)) => Ordering::Greater,
(KnownInstanceType::TypeVar(left), KnownInstanceType::TypeVar(right)) => { (KnownInstanceType::TypeVar(left), KnownInstanceType::TypeVar(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right) left.cmp(right)
} }
} }
@@ -325,7 +364,10 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::KnownInstance(_), _) => Ordering::Less, (Type::KnownInstance(_), _) => Ordering::Less,
(_, Type::KnownInstance(_)) => Ordering::Greater, (_, Type::KnownInstance(_)) => Ordering::Greater,
(Type::PropertyInstance(left), Type::PropertyInstance(right)) => left.cmp(right), (Type::PropertyInstance(left), Type::PropertyInstance(right)) => {
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
left.cmp(right)
}
(Type::PropertyInstance(_), _) => Ordering::Less, (Type::PropertyInstance(_), _) => Ordering::Less,
(_, Type::PropertyInstance(_)) => Ordering::Greater, (_, Type::PropertyInstance(_)) => Ordering::Greater,