mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 05:14:52 +00:00
[ty] Add some additional type safety to CycleDetector
(#19903)
This PR adds a type tag to the `CycleDetector` visitor (and its aliases). There are some places where we implement e.g. an equivalence check by making a disjointness check. Both `is_equivalent_to` and `is_disjoint_from` use a `PairVisitor` to handle cycles, but they should not use the same visitor. I was finding it tedious to remember when it was appropriate to pass on a visitor and when not to. This adds a `PhantomData` type tag to ensure that we can't pass on one method's visitor to a different method. For `has_relation` and `apply_type_mapping`, we have an existing type that we can use as the tag. For the other methods, I've added empty structs (`Normalized`, `IsDisjointFrom`, `IsEquivalentTo`) to use as tags.
This commit is contained in:
parent
df0648aae0
commit
baadb5a78d
11 changed files with 155 additions and 105 deletions
|
@ -170,6 +170,24 @@ fn definition_expression_type<'db>(
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`TypeTransformer`] that is used in `apply_type_mapping` methods.
|
||||
pub(crate) type ApplyTypeMappingVisitor<'db> = TypeTransformer<'db, TypeMapping<'db, 'db>>;
|
||||
|
||||
/// A [`PairVisitor`] that is used in `has_relation_to` methods.
|
||||
pub(crate) type HasRelationToVisitor<'db> = PairVisitor<'db, TypeRelation>;
|
||||
|
||||
/// A [`PairVisitor`] that is used in `is_disjoint_from` methods.
|
||||
pub(crate) type IsDisjointVisitor<'db> = PairVisitor<'db, IsDisjoint>;
|
||||
pub(crate) struct IsDisjoint;
|
||||
|
||||
/// A [`PairVisitor`] that is used in `is_equivalent` methods.
|
||||
pub(crate) type IsEquivalentVisitor<'db> = PairVisitor<'db, IsEquivalent>;
|
||||
pub(crate) struct IsEquivalent;
|
||||
|
||||
/// A [`TypeTransformer`] that is used in `normalized` methods.
|
||||
pub(crate) type NormalizedVisitor<'db> = TypeTransformer<'db, Normalized>;
|
||||
pub(crate) struct Normalized;
|
||||
|
||||
/// The descriptor protocol distinguishes two kinds of descriptors. Non-data descriptors
|
||||
/// define a `__get__` method, while data descriptors additionally define a `__set__`
|
||||
/// method or a `__delete__` method. This enum is used to categorize attributes into two
|
||||
|
@ -419,7 +437,7 @@ impl<'db> PropertyInstanceType<'db> {
|
|||
Self::new(db, getter, setter)
|
||||
}
|
||||
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.getter(db).map(|ty| ty.normalized_impl(db, visitor)),
|
||||
|
@ -1068,7 +1086,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
Type::Union(union) => {
|
||||
visitor.visit(self, || Type::Union(union.normalized_impl(db, visitor)))
|
||||
|
@ -1326,7 +1344,7 @@ impl<'db> Type<'db> {
|
|||
db: &'db dyn Db,
|
||||
target: Type<'db>,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
// Subtyping implies assignability, so if subtyping is reflexive and the two types are
|
||||
// equal, it is both a subtype and assignable. Assignability is always reflexive.
|
||||
|
@ -1762,7 +1780,7 @@ impl<'db> Type<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
other: Type<'db>,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsEquivalentVisitor<'db>,
|
||||
) -> bool {
|
||||
if self == other {
|
||||
return true;
|
||||
|
@ -1848,13 +1866,13 @@ impl<'db> Type<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
other: Type<'db>,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
fn any_protocol_members_absent_or_disjoint<'db>(
|
||||
db: &'db dyn Db,
|
||||
protocol: ProtocolInstanceType<'db>,
|
||||
other: Type<'db>,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
protocol.interface(db).members(db).any(|member| {
|
||||
other
|
||||
|
@ -5743,7 +5761,7 @@ impl<'db> Type<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Type<'db> {
|
||||
match self {
|
||||
Type::TypeVar(bound_typevar) => match type_mapping {
|
||||
|
@ -6265,7 +6283,7 @@ impl<'db> TypeMapping<'_, 'db> {
|
|||
}
|
||||
}
|
||||
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
TypeMapping::Specialization(specialization) => {
|
||||
TypeMapping::Specialization(specialization.normalized_impl(db, visitor))
|
||||
|
@ -6351,7 +6369,7 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
|||
}
|
||||
|
||||
impl<'db> KnownInstanceType<'db> {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
Self::SubscriptedProtocol(context) => {
|
||||
Self::SubscriptedProtocol(context.normalized_impl(db, visitor))
|
||||
|
@ -6777,7 +6795,7 @@ pub struct FieldInstance<'db> {
|
|||
impl get_size2::GetSize for FieldInstance<'_> {}
|
||||
|
||||
impl<'db> FieldInstance<'db> {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
FieldInstance::new(
|
||||
db,
|
||||
self.default_type(db).normalized_impl(db, visitor),
|
||||
|
@ -6901,7 +6919,7 @@ impl<'db> TypeVarInstance<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.name(db),
|
||||
|
@ -6997,7 +7015,7 @@ impl<'db> BoundTypeVarInstance<'db> {
|
|||
.map(|ty| ty.apply_type_mapping(db, &TypeMapping::BindLegacyTypevars(binding_context)))
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.typevar(db).normalized_impl(db, visitor),
|
||||
|
@ -7056,7 +7074,7 @@ fn walk_type_var_bounds<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
|||
}
|
||||
|
||||
impl<'db> TypeVarBoundOrConstraints<'db> {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
TypeVarBoundOrConstraints::UpperBound(bound) => {
|
||||
TypeVarBoundOrConstraints::UpperBound(bound.normalized_impl(db, visitor))
|
||||
|
@ -8094,7 +8112,7 @@ impl<'db> BoundMethodType<'db> {
|
|||
)
|
||||
}
|
||||
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.function(db).normalized_impl(db, visitor),
|
||||
|
@ -8211,7 +8229,7 @@ impl<'db> CallableType<'db> {
|
|||
/// Return a "normalized" version of this `Callable` type.
|
||||
///
|
||||
/// See [`Type::normalized`] for more details.
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
CallableType::new(
|
||||
db,
|
||||
self.signatures(db).normalized_impl(db, visitor),
|
||||
|
@ -8375,7 +8393,7 @@ impl<'db> MethodWrapperKind<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
MethodWrapperKind::FunctionTypeDunderGet(function) => {
|
||||
MethodWrapperKind::FunctionTypeDunderGet(function.normalized_impl(db, visitor))
|
||||
|
@ -8559,7 +8577,7 @@ impl<'db> PEP695TypeAliasType<'db> {
|
|||
definition_expression_type(db, definition, &type_alias_stmt_node.value)
|
||||
}
|
||||
|
||||
fn normalized_impl(self, _db: &'db dyn Db, _visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, _db: &'db dyn Db, _visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -8601,7 +8619,7 @@ fn walk_bare_type_alias<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
|||
}
|
||||
|
||||
impl<'db> BareTypeAliasType<'db> {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.name(db),
|
||||
|
@ -8637,7 +8655,7 @@ fn walk_type_alias_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
|||
}
|
||||
|
||||
impl<'db> TypeAliasType<'db> {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
TypeAliasType::PEP695(type_alias) => {
|
||||
TypeAliasType::PEP695(type_alias.normalized_impl(db, visitor))
|
||||
|
@ -8866,7 +8884,7 @@ impl<'db> UnionType<'db> {
|
|||
self.normalized_impl(db, &TypeTransformer::default())
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let mut new_elements: Vec<Type<'db>> = self
|
||||
.elements(db)
|
||||
.iter()
|
||||
|
@ -8940,11 +8958,11 @@ impl<'db> IntersectionType<'db> {
|
|||
self.normalized_impl(db, &TypeTransformer::default())
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
fn normalized_set<'db>(
|
||||
db: &'db dyn Db,
|
||||
elements: &FxOrderSet<Type<'db>>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> FxOrderSet<Type<'db>> {
|
||||
let mut elements: FxOrderSet<Type<'db>> = elements
|
||||
.iter()
|
||||
|
@ -9194,7 +9212,7 @@ impl<'db> TypedDictType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
Self {
|
||||
defining_class: self
|
||||
|
@ -9266,7 +9284,7 @@ pub enum SuperOwnerKind<'db> {
|
|||
}
|
||||
|
||||
impl<'db> SuperOwnerKind<'db> {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
SuperOwnerKind::Dynamic(dynamic) => SuperOwnerKind::Dynamic(dynamic.normalized()),
|
||||
SuperOwnerKind::Class(class) => {
|
||||
|
@ -9538,7 +9556,7 @@ impl<'db> BoundSuperType<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.pivot_class(db).normalized_impl(db, visitor),
|
||||
|
|
|
@ -22,10 +22,11 @@ use crate::types::infer::nearest_enclosing_class;
|
|||
use crate::types::signatures::{CallableSignature, Parameter, Parameters, Signature};
|
||||
use crate::types::tuple::{TupleSpec, TupleType};
|
||||
use crate::types::{
|
||||
BareTypeAliasType, Binding, BoundSuperError, BoundSuperType, CallableType, DataclassParams,
|
||||
DeprecatedInstance, KnownInstanceType, StringLiteralType, TypeAliasType, TypeMapping,
|
||||
TypeRelation, TypeTransformer, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind,
|
||||
declaration_type, infer_definition_types, todo_type,
|
||||
ApplyTypeMappingVisitor, BareTypeAliasType, Binding, BoundSuperError, BoundSuperType,
|
||||
CallableType, DataclassParams, DeprecatedInstance, HasRelationToVisitor, KnownInstanceType,
|
||||
NormalizedVisitor, StringLiteralType, TypeAliasType, TypeMapping, TypeRelation,
|
||||
TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, declaration_type,
|
||||
infer_definition_types, todo_type,
|
||||
};
|
||||
use crate::{
|
||||
Db, FxIndexMap, FxOrderSet, Program,
|
||||
|
@ -231,7 +232,7 @@ pub(super) fn walk_generic_alias<'db, V: super::visitor::TypeVisitor<'db> + ?Siz
|
|||
impl get_size2::GetSize for GenericAlias<'_> {}
|
||||
|
||||
impl<'db> GenericAlias<'db> {
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.origin(db),
|
||||
|
@ -255,7 +256,7 @@ impl<'db> GenericAlias<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
|
@ -319,7 +320,7 @@ impl<'db> ClassType<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
Self::NonGeneric(_) => self,
|
||||
Self::Generic(generic) => Self::Generic(generic.normalized_impl(db, visitor)),
|
||||
|
@ -406,7 +407,7 @@ impl<'db> ClassType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
match self {
|
||||
Self::NonGeneric(_) => self,
|
||||
|
@ -469,7 +470,7 @@ impl<'db> ClassType<'db> {
|
|||
db: &'db dyn Db,
|
||||
other: Self,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
self.iter_mro(db).any(|base| {
|
||||
match base {
|
||||
|
|
|
@ -2,8 +2,9 @@ use crate::Db;
|
|||
use crate::types::generics::Specialization;
|
||||
use crate::types::tuple::TupleType;
|
||||
use crate::types::{
|
||||
ClassLiteral, ClassType, DynamicType, KnownClass, KnownInstanceType, MroError, MroIterator,
|
||||
SpecialFormType, Type, TypeMapping, TypeTransformer, todo_type,
|
||||
ApplyTypeMappingVisitor, ClassLiteral, ClassType, DynamicType, KnownClass, KnownInstanceType,
|
||||
MroError, MroIterator, NormalizedVisitor, SpecialFormType, Type, TypeMapping, TypeTransformer,
|
||||
todo_type,
|
||||
};
|
||||
|
||||
/// Enumeration of the possible kinds of types we allow in class bases.
|
||||
|
@ -33,7 +34,7 @@ impl<'db> ClassBase<'db> {
|
|||
Self::Dynamic(DynamicType::Unknown)
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
Self::Dynamic(dynamic) => Self::Dynamic(dynamic.normalized()),
|
||||
Self::Class(class) => Self::Class(class.normalized_impl(db, visitor)),
|
||||
|
@ -269,7 +270,7 @@ impl<'db> ClassBase<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
match self {
|
||||
Self::Class(class) => {
|
||||
|
|
|
@ -18,17 +18,20 @@
|
|||
//! `visitor.visit` when visiting a protocol type, and then internal `has_relation_to_impl` methods
|
||||
//! of the Rust types implementing protocols also call `visitor.visit`. The best way to avoid this
|
||||
//! is to prefer always calling `visitor.visit` only in the main recursive method on `Type`.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Eq;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::FxIndexSet;
|
||||
use crate::types::Type;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Eq;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub(crate) type TypeTransformer<'db> = CycleDetector<Type<'db>, Type<'db>>;
|
||||
pub(crate) type TypeTransformer<'db, Tag> = CycleDetector<Tag, Type<'db>, Type<'db>>;
|
||||
|
||||
impl Default for TypeTransformer<'_> {
|
||||
impl<Tag> Default for TypeTransformer<'_, Tag> {
|
||||
fn default() -> Self {
|
||||
// TODO: proper recursive type handling
|
||||
|
||||
|
@ -38,10 +41,10 @@ impl Default for TypeTransformer<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type PairVisitor<'db> = CycleDetector<(Type<'db>, Type<'db>), bool>;
|
||||
pub(crate) type PairVisitor<'db, Tag> = CycleDetector<Tag, (Type<'db>, Type<'db>), bool>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CycleDetector<T, R> {
|
||||
pub(crate) struct CycleDetector<Tag, T, R> {
|
||||
/// If the type we're visiting is present in `seen`, it indicates that we've hit a cycle (due
|
||||
/// to a recursive type); we need to immediately short circuit the whole operation and return
|
||||
/// the fallback value. That's why we pop items off the end of `seen` after we've visited them.
|
||||
|
@ -56,14 +59,17 @@ pub(crate) struct CycleDetector<T, R> {
|
|||
cache: RefCell<FxHashMap<T, R>>,
|
||||
|
||||
fallback: R,
|
||||
|
||||
_tag: PhantomData<Tag>,
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq + Copy, R: Copy> CycleDetector<T, R> {
|
||||
impl<Tag, T: Hash + Eq + Copy, R: Copy> CycleDetector<Tag, T, R> {
|
||||
pub(crate) fn new(fallback: R) -> Self {
|
||||
CycleDetector {
|
||||
seen: RefCell::new(FxIndexSet::default()),
|
||||
cache: RefCell::new(FxHashMap::default()),
|
||||
fallback,
|
||||
_tag: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ use crate::types::signatures::{CallableSignature, Signature};
|
|||
use crate::types::visitor::any_over_type;
|
||||
use crate::types::{
|
||||
BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, ClassType,
|
||||
DeprecatedInstance, DynamicType, KnownClass, Truthiness, Type, TypeMapping, TypeRelation,
|
||||
TypeTransformer, UnionBuilder, all_members, walk_type_mapping,
|
||||
DeprecatedInstance, DynamicType, KnownClass, NormalizedVisitor, Truthiness, Type, TypeMapping,
|
||||
TypeRelation, TypeTransformer, UnionBuilder, all_members, walk_type_mapping,
|
||||
};
|
||||
use crate::{Db, FxOrderSet, ModuleName, resolve_module};
|
||||
|
||||
|
@ -604,7 +604,7 @@ impl<'db> FunctionLiteral<'db> {
|
|||
)
|
||||
}
|
||||
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let context = self
|
||||
.inherited_generic_context(db)
|
||||
.map(|ctx| ctx.normalized_impl(db, visitor));
|
||||
|
@ -923,7 +923,7 @@ impl<'db> FunctionType<'db> {
|
|||
self.normalized_impl(db, &TypeTransformer::default())
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let mappings: Box<_> = self
|
||||
.type_mappings(db)
|
||||
.iter()
|
||||
|
|
|
@ -14,9 +14,10 @@ use crate::types::instance::{Protocol, ProtocolInstanceType};
|
|||
use crate::types::signatures::{Parameter, Parameters, Signature};
|
||||
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
|
||||
use crate::types::{
|
||||
BoundTypeVarInstance, KnownClass, KnownInstanceType, Type, TypeMapping, TypeRelation,
|
||||
TypeTransformer, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance, UnionType,
|
||||
binding_type, cyclic::PairVisitor, declaration_type,
|
||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, KnownClass,
|
||||
KnownInstanceType, NormalizedVisitor, Type, TypeMapping, TypeRelation, TypeTransformer,
|
||||
TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance, UnionType, binding_type,
|
||||
declaration_type,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
|
@ -355,7 +356,7 @@ impl<'db> GenericContext<'db> {
|
|||
Specialization::new(db, self, expanded.into_boxed_slice(), None)
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let variables: FxOrderSet<_> = self
|
||||
.variables(db)
|
||||
.iter()
|
||||
|
@ -471,7 +472,7 @@ impl<'db> Specialization<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
let types: Box<[_]> = self
|
||||
.types(db)
|
||||
|
@ -522,7 +523,7 @@ impl<'db> Specialization<'db> {
|
|||
Specialization::new(db, self.generic_context(db), types, None)
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let types: Box<[_]> = self
|
||||
.types(db)
|
||||
.iter()
|
||||
|
@ -563,7 +564,7 @@ impl<'db> Specialization<'db> {
|
|||
db: &'db dyn Db,
|
||||
other: Self,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
let generic_context = self.generic_context(db);
|
||||
if generic_context != other.generic_context(db) {
|
||||
|
@ -716,7 +717,7 @@ impl<'db> PartialSpecialization<'_, 'db> {
|
|||
pub(crate) fn normalized_impl(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> PartialSpecialization<'db, 'db> {
|
||||
let generic_context = self.generic_context.normalized_impl(db, visitor);
|
||||
let types: Cow<_> = self
|
||||
|
|
|
@ -7,11 +7,13 @@ use super::protocol_class::ProtocolInterface;
|
|||
use super::{BoundTypeVarInstance, ClassType, KnownClass, SubclassOfType, Type, TypeVarVariance};
|
||||
use crate::place::PlaceAndQualifiers;
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::types::cyclic::PairVisitor;
|
||||
use crate::types::enums::is_single_member_enum;
|
||||
use crate::types::protocol_class::walk_protocol_interface;
|
||||
use crate::types::tuple::{TupleSpec, TupleType};
|
||||
use crate::types::{ClassBase, DynamicType, TypeMapping, TypeRelation, TypeTransformer};
|
||||
use crate::types::{
|
||||
ApplyTypeMappingVisitor, ClassBase, DynamicType, HasRelationToVisitor, IsDisjointVisitor,
|
||||
NormalizedVisitor, TypeMapping, TypeRelation, TypeTransformer,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
pub(super) use synthesized_protocol::SynthesizedProtocolType;
|
||||
|
@ -241,7 +243,7 @@ impl<'db> NominalInstanceType<'db> {
|
|||
pub(super) fn normalized_impl(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Type<'db> {
|
||||
match self.0 {
|
||||
NominalInstanceInner::ExactTuple(tuple) => {
|
||||
|
@ -267,7 +269,7 @@ impl<'db> NominalInstanceType<'db> {
|
|||
db: &'db dyn Db,
|
||||
other: Self,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
match (self.0, other.0) {
|
||||
(
|
||||
|
@ -297,7 +299,7 @@ impl<'db> NominalInstanceType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
other: Self,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
if let Some(self_spec) = self.tuple_spec(db) {
|
||||
if let Some(other_spec) = other.tuple_spec(db) {
|
||||
|
@ -345,7 +347,7 @@ impl<'db> NominalInstanceType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Type<'db> {
|
||||
match self.0 {
|
||||
NominalInstanceInner::ExactTuple(tuple) => {
|
||||
|
@ -480,7 +482,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
|||
pub(super) fn normalized_impl(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Type<'db> {
|
||||
let object = Type::object(db);
|
||||
if object.satisfies_protocol(db, self, TypeRelation::Subtyping) {
|
||||
|
@ -532,7 +534,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
|||
self,
|
||||
_db: &'db dyn Db,
|
||||
_other: Self,
|
||||
_visitor: &PairVisitor<'db>,
|
||||
_visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
@ -558,7 +560,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
match self.inner {
|
||||
Protocol::FromClass(class) => {
|
||||
|
@ -619,7 +621,10 @@ impl<'db> Protocol<'db> {
|
|||
mod synthesized_protocol {
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::types::protocol_class::ProtocolInterface;
|
||||
use crate::types::{BoundTypeVarInstance, TypeMapping, TypeTransformer, TypeVarVariance};
|
||||
use crate::types::{
|
||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, NormalizedVisitor, TypeMapping,
|
||||
TypeVarVariance,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
/// A "synthesized" protocol type that is dissociated from a class definition in source code.
|
||||
|
@ -640,7 +645,7 @@ mod synthesized_protocol {
|
|||
pub(super) fn new(
|
||||
db: &'db dyn Db,
|
||||
interface: ProtocolInterface<'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Self {
|
||||
Self(interface.normalized_impl(db, visitor))
|
||||
}
|
||||
|
@ -653,7 +658,7 @@ mod synthesized_protocol {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
_visitor: &TypeTransformer<'db>,
|
||||
_visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
Self(self.0.specialized_and_normalized(db, type_mapping))
|
||||
}
|
||||
|
|
|
@ -12,10 +12,9 @@ use crate::{
|
|||
place::{Boundness, Place, PlaceAndQualifiers, place_from_bindings, place_from_declarations},
|
||||
semantic_index::{definition::Definition, use_def_map},
|
||||
types::{
|
||||
BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, KnownFunction,
|
||||
PropertyInstanceType, Signature, Type, TypeMapping, TypeQualifiers, TypeRelation,
|
||||
TypeTransformer,
|
||||
cyclic::PairVisitor,
|
||||
BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, IsDisjointVisitor,
|
||||
KnownFunction, NormalizedVisitor, PropertyInstanceType, Signature, Type, TypeMapping,
|
||||
TypeQualifiers, TypeRelation, TypeTransformer,
|
||||
signatures::{Parameter, Parameters},
|
||||
},
|
||||
};
|
||||
|
@ -165,7 +164,7 @@ impl<'db> ProtocolInterface<'db> {
|
|||
.all(|member_name| other.inner(db).contains_key(member_name))
|
||||
}
|
||||
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(super) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::new(
|
||||
db,
|
||||
self.inner(db)
|
||||
|
@ -252,7 +251,7 @@ impl<'db> ProtocolMemberData<'db> {
|
|||
self.normalized_impl(db, &TypeTransformer::default())
|
||||
}
|
||||
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self {
|
||||
kind: self.kind.normalized_impl(db, visitor),
|
||||
qualifiers: self.qualifiers,
|
||||
|
@ -327,7 +326,7 @@ enum ProtocolMemberKind<'db> {
|
|||
}
|
||||
|
||||
impl<'db> ProtocolMemberKind<'db> {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
ProtocolMemberKind::Method(callable) => {
|
||||
ProtocolMemberKind::Method(callable.normalized_impl(db, visitor))
|
||||
|
@ -432,7 +431,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
|||
&self,
|
||||
db: &'db dyn Db,
|
||||
other: Type<'db>,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
match &self.kind {
|
||||
// TODO: implement disjointness for property/method members as well as attribute members
|
||||
|
|
|
@ -15,10 +15,12 @@ use std::{collections::HashMap, slice::Iter};
|
|||
use itertools::EitherOrBoth;
|
||||
use smallvec::{SmallVec, smallvec_inline};
|
||||
|
||||
use super::{DynamicType, Type, TypeTransformer, TypeVarVariance, definition_expression_type};
|
||||
use super::{DynamicType, Type, TypeVarVariance, definition_expression_type};
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::types::generics::{GenericContext, walk_generic_context};
|
||||
use crate::types::{BoundTypeVarInstance, KnownClass, TypeMapping, TypeRelation, todo_type};
|
||||
use crate::types::{
|
||||
BoundTypeVarInstance, KnownClass, NormalizedVisitor, TypeMapping, TypeRelation, todo_type,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
use ruff_python_ast::{self as ast, name::Name};
|
||||
|
||||
|
@ -61,7 +63,11 @@ impl<'db> CallableSignature<'db> {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Self {
|
||||
Self::from_overloads(
|
||||
self.overloads
|
||||
.iter()
|
||||
|
@ -380,7 +386,11 @@ impl<'db> Signature<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Self {
|
||||
Self {
|
||||
generic_context: self
|
||||
.generic_context
|
||||
|
@ -1360,7 +1370,11 @@ impl<'db> Parameter<'db> {
|
|||
/// Normalize nested unions and intersections in the annotated type, if any.
|
||||
///
|
||||
/// See [`Type::normalized`] for more details.
|
||||
pub(crate) fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Self {
|
||||
let Parameter {
|
||||
annotated_type,
|
||||
kind,
|
||||
|
|
|
@ -3,8 +3,9 @@ use ruff_python_ast::name::Name;
|
|||
use crate::place::PlaceAndQualifiers;
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::types::{
|
||||
BindingContext, BoundTypeVarInstance, ClassType, DynamicType, KnownClass, MemberLookupPolicy,
|
||||
Type, TypeMapping, TypeRelation, TypeTransformer, TypeVarInstance, cyclic::PairVisitor,
|
||||
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, ClassType, DynamicType,
|
||||
HasRelationToVisitor, KnownClass, MemberLookupPolicy, NormalizedVisitor, Type, TypeMapping,
|
||||
TypeRelation, TypeVarInstance,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
|
@ -116,7 +117,7 @@ impl<'db> SubclassOfType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
match self.subclass_of {
|
||||
SubclassOfInner::Class(class) => Self {
|
||||
|
@ -159,7 +160,7 @@ impl<'db> SubclassOfType<'db> {
|
|||
db: &'db dyn Db,
|
||||
other: SubclassOfType<'db>,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
match (self.subclass_of, other.subclass_of) {
|
||||
(SubclassOfInner::Dynamic(_), SubclassOfInner::Dynamic(_)) => {
|
||||
|
@ -191,7 +192,7 @@ impl<'db> SubclassOfType<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self {
|
||||
subclass_of: self.subclass_of.normalized_impl(db, visitor),
|
||||
}
|
||||
|
@ -254,7 +255,7 @@ impl<'db> SubclassOfInner<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
Self::Class(class) => Self::Class(class.normalized_impl(db, visitor)),
|
||||
Self::Dynamic(dynamic) => Self::Dynamic(dynamic.normalized()),
|
||||
|
|
|
@ -25,8 +25,8 @@ use crate::semantic_index::definition::Definition;
|
|||
use crate::types::Truthiness;
|
||||
use crate::types::class::{ClassType, KnownClass};
|
||||
use crate::types::{
|
||||
BoundTypeVarInstance, Type, TypeMapping, TypeRelation, TypeTransformer, TypeVarVariance,
|
||||
UnionBuilder, UnionType, cyclic::PairVisitor,
|
||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, IsDisjointVisitor,
|
||||
NormalizedVisitor, Type, TypeMapping, TypeRelation, TypeVarVariance, UnionBuilder, UnionType,
|
||||
};
|
||||
use crate::util::subscript::{Nth, OutOfBoundsError, PyIndex, PySlice, StepSizeZeroError};
|
||||
use crate::{Db, FxOrderSet, Program};
|
||||
|
@ -221,7 +221,7 @@ impl<'db> TupleType<'db> {
|
|||
pub(crate) fn normalized_impl(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Option<Self> {
|
||||
TupleType::new(db, &self.tuple(db).normalized_impl(db, visitor))
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ impl<'db> TupleType<'db> {
|
|||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Option<Self> {
|
||||
TupleType::new(
|
||||
db,
|
||||
|
@ -259,7 +259,7 @@ impl<'db> TupleType<'db> {
|
|||
db: &'db dyn Db,
|
||||
other: Self,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
self.tuple(db)
|
||||
.has_relation_to_impl(db, other.tuple(db), relation, visitor)
|
||||
|
@ -377,7 +377,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self::from_elements(self.0.iter().map(|ty| ty.normalized_impl(db, visitor)))
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
|||
&self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
Self::from_elements(
|
||||
self.0
|
||||
|
@ -414,7 +414,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
|||
db: &'db dyn Db,
|
||||
other: &Tuple<Type<'db>>,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
match other {
|
||||
Tuple::Fixed(other) => {
|
||||
|
@ -658,7 +658,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> TupleSpec<'db> {
|
||||
fn normalized_impl(&self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> TupleSpec<'db> {
|
||||
let prefix = self
|
||||
.prenormalized_prefix_elements(db, None)
|
||||
.map(|ty| ty.normalized_impl(db, visitor))
|
||||
|
@ -687,7 +687,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
|||
&self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> TupleSpec<'db> {
|
||||
Self::mixed(
|
||||
self.prefix
|
||||
|
@ -722,7 +722,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
|||
db: &'db dyn Db,
|
||||
other: &Tuple<Type<'db>>,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
match other {
|
||||
Tuple::Fixed(other) => {
|
||||
|
@ -983,7 +983,11 @@ impl<'db> Tuple<Type<'db>> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(&self, db: &'db dyn Db, visitor: &TypeTransformer<'db>) -> Self {
|
||||
pub(crate) fn normalized_impl(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
visitor: &NormalizedVisitor<'db>,
|
||||
) -> Self {
|
||||
match self {
|
||||
Tuple::Fixed(tuple) => Tuple::Fixed(tuple.normalized_impl(db, visitor)),
|
||||
Tuple::Variable(tuple) => tuple.normalized_impl(db, visitor),
|
||||
|
@ -1001,7 +1005,7 @@ impl<'db> Tuple<Type<'db>> {
|
|||
&self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
visitor: &TypeTransformer<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
match self {
|
||||
Tuple::Fixed(tuple) => {
|
||||
|
@ -1028,7 +1032,7 @@ impl<'db> Tuple<Type<'db>> {
|
|||
db: &'db dyn Db,
|
||||
other: &Self,
|
||||
relation: TypeRelation,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &HasRelationToVisitor<'db>,
|
||||
) -> bool {
|
||||
match self {
|
||||
Tuple::Fixed(self_tuple) => {
|
||||
|
@ -1056,7 +1060,7 @@ impl<'db> Tuple<Type<'db>> {
|
|||
&self,
|
||||
db: &'db dyn Db,
|
||||
other: &Self,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool {
|
||||
// Two tuples with an incompatible number of required elements must always be disjoint.
|
||||
let (self_min, self_max) = self.len().size_hint();
|
||||
|
@ -1074,7 +1078,7 @@ impl<'db> Tuple<Type<'db>> {
|
|||
db: &'db dyn Db,
|
||||
a: impl IntoIterator<Item = &'s Type<'db>>,
|
||||
b: impl IntoIterator<Item = &'s Type<'db>>,
|
||||
visitor: &PairVisitor<'db>,
|
||||
visitor: &IsDisjointVisitor<'db>,
|
||||
) -> bool
|
||||
where
|
||||
'db: 's,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue