mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
[ty] Deterministic ordering of types
This commit is contained in:
parent
2a217e80ca
commit
3a76557be2
6 changed files with 163 additions and 33 deletions
|
@ -1,6 +1,7 @@
|
|||
use infer::enclosing_class_symbol;
|
||||
use itertools::Either;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::slice::Iter;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -7973,6 +7974,10 @@ impl<'db> StringLiteralType<'db> {
|
|||
.chars()
|
||||
.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)]
|
||||
|
@ -7985,6 +7990,10 @@ impl<'db> BytesLiteralType<'db> {
|
|||
pub(crate) fn python_len(self, db: &'db dyn Db) -> usize {
|
||||
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)]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
|
@ -187,6 +188,15 @@ impl<'db> GenericAlias<'db> {
|
|||
) {
|
||||
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> {
|
||||
|
@ -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
|
||||
/// class.
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Supertype, salsa::Update,
|
||||
)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Supertype, salsa::Update)]
|
||||
pub enum ClassType<'db> {
|
||||
NonGeneric(ClassLiteral<'db>),
|
||||
Generic(GenericAlias<'db>),
|
||||
|
@ -470,6 +478,15 @@ impl<'db> ClassType<'db> {
|
|||
.own_instance_member(db, name)
|
||||
.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> {
|
||||
|
@ -506,6 +523,14 @@ pub struct ClassLiteral<'db> {
|
|||
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).cmp(&other.body_scope(db)))
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(clippy::trivially_copy_pass_by_ref, clippy::ref_option)]
|
||||
fn pep695_generic_context_cycle_recover<'db>(
|
||||
_db: &'db dyn Db,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use ruff_python_ast as ast;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
|
@ -7,8 +9,9 @@ use crate::types::class_base::ClassBase;
|
|||
use crate::types::instance::{NominalInstanceType, Protocol, ProtocolInstanceType};
|
||||
use crate::types::signatures::{Parameter, Parameters, Signature};
|
||||
use crate::types::{
|
||||
declaration_type, todo_type, KnownInstanceType, Type, TypeVarBoundOrConstraints,
|
||||
TypeVarInstance, TypeVarVariance, UnionType,
|
||||
declaration_type, todo_type, type_ordering::union_or_intersection_elements_ordering,
|
||||
KnownInstanceType, Type, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
|
||||
UnionType,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
|
@ -229,9 +232,15 @@ impl<'db> GenericContext<'db> {
|
|||
|
||||
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 {
|
||||
LegacyBase(LegacyGenericBase),
|
||||
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 {
|
||||
Generic,
|
||||
Protocol,
|
||||
|
@ -518,6 +527,20 @@ impl<'db> Specialization<'db> {
|
|||
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(|| {
|
||||
self.types(db)
|
||||
.iter()
|
||||
.zip(other.types(db))
|
||||
.map(|(self_type, other_type)| {
|
||||
union_or_intersection_elements_ordering(db, self_type, other_type)
|
||||
})
|
||||
.fold(Ordering::Equal, Ordering::then)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A mapping between type variables and types.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Instance types: both nominal and structural.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
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
|
||||
/// 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(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
|
||||
/// 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> {
|
||||
FromClass(ClassType<'db>),
|
||||
Synthesized(SynthesizedProtocolType<'db>),
|
||||
|
@ -353,9 +358,20 @@ impl<'db> Protocol<'db> {
|
|||
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 {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::types::generics::TypeMapping;
|
||||
use crate::types::protocol_class::ProtocolInterface;
|
||||
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
|
||||
/// 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>);
|
||||
|
||||
impl<'db> SynthesizedProtocolType<'db> {
|
||||
|
@ -397,5 +413,9 @@ mod synthesized_protocol {
|
|||
pub(in crate::types) fn interface(self) -> ProtocolInterface<'db> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub(super) fn ordering(self, db: &'db dyn Db, other: Self) -> Ordering {
|
||||
self.0.ordering(db, other.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::BTreeMap, ops::Deref};
|
||||
use std::{cmp::Ordering, collections::BTreeMap, ops::Deref};
|
||||
|
||||
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.
|
||||
#[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> {
|
||||
Members(ProtocolInterfaceMembers<'db>),
|
||||
SelfReference,
|
||||
|
@ -205,6 +205,17 @@ impl<'db> ProtocolInterface<'db> {
|
|||
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)]
|
||||
|
|
|
@ -56,23 +56,32 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
(Type::IntLiteral(_), _) => Ordering::Less,
|
||||
(_, 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::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::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::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::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::Greater,
|
||||
|
||||
|
@ -92,29 +101,40 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
(Type::DataclassTransformer(_), _) => Ordering::Less,
|
||||
(_, 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::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::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::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::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::Greater,
|
||||
|
||||
(Type::SubclassOf(left), Type::SubclassOf(right)) => {
|
||||
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::Greater,
|
||||
(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::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::Greater,
|
||||
|
||||
(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::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::Greater,
|
||||
|
||||
|
@ -148,15 +173,21 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
|
||||
(Type::BoundSuper(left), Type::BoundSuper(right)) => {
|
||||
(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::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::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::Greater,
|
||||
|
||||
|
@ -165,11 +196,13 @@ pub(super) fn union_or_intersection_elements_ordering<'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::Greater,
|
||||
(SuperOwnerKind::Instance(left), SuperOwnerKind::Instance(right)) => {
|
||||
left.class.cmp(&right.class)
|
||||
left.class.ordering(db, right.class)
|
||||
}
|
||||
(SuperOwnerKind::Instance(_), _) => Ordering::Less,
|
||||
(_, SuperOwnerKind::Instance(_)) => Ordering::Greater,
|
||||
|
@ -247,12 +280,14 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
(_, KnownInstanceType::OrderedDict) => Ordering::Greater,
|
||||
|
||||
(KnownInstanceType::Generic(left), KnownInstanceType::Generic(right)) => {
|
||||
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
|
||||
left.cmp(right)
|
||||
}
|
||||
(KnownInstanceType::Generic(_), _) => Ordering::Less,
|
||||
(_, KnownInstanceType::Generic(_)) => Ordering::Greater,
|
||||
|
||||
(KnownInstanceType::Protocol(left), KnownInstanceType::Protocol(right)) => {
|
||||
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
|
||||
left.cmp(right)
|
||||
}
|
||||
(KnownInstanceType::Protocol(_), _) => Ordering::Less,
|
||||
|
@ -312,11 +347,15 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
(
|
||||
KnownInstanceType::TypeAliasType(left),
|
||||
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::Greater,
|
||||
|
||||
(KnownInstanceType::TypeVar(left), KnownInstanceType::TypeVar(right)) => {
|
||||
// TODO: This compares by salsa ID, which can lead to non-deterministic ordering
|
||||
left.cmp(right)
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +364,10 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
|||
(Type::KnownInstance(_), _) => Ordering::Less,
|
||||
(_, 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::Greater,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue