[ty] add cycle detection for find_legacy_typevars (#20124)

## Summary

Add cycle detection to the `find_legacy_typevars` type method.

## Test Plan

Added mdtest that stack overflowed without this.
This commit is contained in:
Carl Meyer 2025-08-28 09:55:08 -07:00 committed by GitHub
parent f703536977
commit f4362b95d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 188 additions and 102 deletions

View file

@ -217,6 +217,26 @@ def f(x: IntOr, y: OrInt):
reveal_type(y) # revealed: Never
```
### With legacy generic
```py
from typing import Generic, TypeVar
T = TypeVar("T")
type Alias = list["Alias"] | int
class A(Generic[T]):
attr: T
class B(A[Alias]):
pass
def f(b: B):
reveal_type(b) # revealed: B
reveal_type(b.attr) # revealed: list[Alias] | int
```
### Mutually recursive
```py

View file

@ -19,7 +19,7 @@ use ruff_text_size::{Ranged, TextRange};
use type_ordering::union_or_intersection_elements_ordering;
pub(crate) use self::builder::{IntersectionBuilder, UnionBuilder};
pub(crate) use self::cyclic::{PairVisitor, TypeTransformer};
pub(crate) use self::cyclic::{CycleDetector, PairVisitor, TypeTransformer};
pub use self::diagnostic::TypeCheckDiagnostics;
pub(crate) use self::diagnostic::register_lints;
pub(crate) use self::infer::{
@ -191,6 +191,10 @@ pub(crate) struct IsDisjoint;
pub(crate) type IsEquivalentVisitor<'db, C> = PairVisitor<'db, IsEquivalent, C>;
pub(crate) struct IsEquivalent;
/// A [`CycleDetector`] for `find_legacy_typevars` methods.
pub(crate) type FindLegacyTypeVarsVisitor<'db> = CycleDetector<FindLegacyTypeVars, Type<'db>, ()>;
pub(crate) struct FindLegacyTypeVars;
/// A [`TypeTransformer`] that is used in `normalized` methods.
pub(crate) type NormalizedVisitor<'db> = TypeTransformer<'db, Normalized>;
pub(crate) struct Normalized;
@ -503,17 +507,18 @@ impl<'db> PropertyInstanceType<'db> {
)
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
if let Some(ty) = self.getter(db) {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
if let Some(ty) = self.setter(db) {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
@ -6157,6 +6162,21 @@ impl<'db> Type<'db> {
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
) {
self.find_legacy_typevars_impl(
db,
binding_context,
typevars,
&FindLegacyTypeVarsVisitor::default(),
);
}
pub(crate) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self {
Type::NonInferableTypeVar(bound_typevar) | Type::TypeVar(bound_typevar) => {
@ -6171,80 +6191,94 @@ impl<'db> Type<'db> {
}
Type::FunctionLiteral(function) => {
function.find_legacy_typevars(db, binding_context, typevars);
function.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::BoundMethod(method) => {
method
.self_instance(db)
.find_legacy_typevars(db, binding_context, typevars);
method
.function(db)
.find_legacy_typevars(db, binding_context, typevars);
method.self_instance(db).find_legacy_typevars_impl(
db,
binding_context,
typevars,
visitor,
);
method.function(db).find_legacy_typevars_impl(
db,
binding_context,
typevars,
visitor,
);
}
Type::MethodWrapper(
MethodWrapperKind::FunctionTypeDunderGet(function)
| MethodWrapperKind::FunctionTypeDunderCall(function),
) => {
function.find_legacy_typevars(db, binding_context, typevars);
function.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::MethodWrapper(
MethodWrapperKind::PropertyDunderGet(property)
| MethodWrapperKind::PropertyDunderSet(property),
) => {
property.find_legacy_typevars(db, binding_context, typevars);
property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::Callable(callable) => {
callable.find_legacy_typevars(db, binding_context, typevars);
callable.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::PropertyInstance(property) => {
property.find_legacy_typevars(db, binding_context, typevars);
property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::Union(union) => {
for element in union.elements(db) {
element.find_legacy_typevars(db, binding_context, typevars);
element.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
Type::Intersection(intersection) => {
for positive in intersection.positive(db) {
positive.find_legacy_typevars(db, binding_context, typevars);
positive.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
for negative in intersection.negative(db) {
negative.find_legacy_typevars(db, binding_context, typevars);
negative.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
Type::GenericAlias(alias) => {
alias.find_legacy_typevars(db, binding_context, typevars);
alias.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::NominalInstance(instance) => {
instance.find_legacy_typevars(db, binding_context, typevars);
instance.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::ProtocolInstance(instance) => {
instance.find_legacy_typevars(db, binding_context, typevars);
instance.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::SubclassOf(subclass_of) => {
subclass_of.find_legacy_typevars(db, binding_context, typevars);
subclass_of.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Type::TypeIs(type_is) => {
type_is
.return_type(db)
.find_legacy_typevars(db, binding_context, typevars);
type_is.return_type(db).find_legacy_typevars_impl(
db,
binding_context,
typevars,
visitor,
);
}
Type::TypeAlias(alias) => {
alias
.value_type(db)
.find_legacy_typevars(db, binding_context, typevars);
visitor.visit(self, || {
alias.value_type(db).find_legacy_typevars_impl(
db,
binding_context,
typevars,
visitor,
);
});
}
Type::Dynamic(_)
@ -8907,14 +8941,15 @@ impl<'db> CallableType<'db> {
)
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
self.signatures(db)
.find_legacy_typevars(db, binding_context, typevars);
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
/// Check whether this callable type has the given relation to another callable type.

View file

@ -30,11 +30,11 @@ use crate::types::tuple::{TupleSpec, TupleType};
use crate::types::typed_dict::typed_dict_params_from_class_def;
use crate::types::{
ApplyTypeMappingVisitor, Binding, BoundSuperError, BoundSuperType, CallableType,
DataclassParams, DeprecatedInstance, HasRelationToVisitor, IsEquivalentVisitor,
KnownInstanceType, ManualPEP695TypeAliasType, MaterializationKind, NormalizedVisitor,
PropertyInstanceType, StringLiteralType, TypeAliasType, TypeMapping, TypeRelation,
TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, TypedDictParams, VarianceInferable,
declaration_type, infer_definition_types, todo_type,
DataclassParams, DeprecatedInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, KnownInstanceType, ManualPEP695TypeAliasType, MaterializationKind,
NormalizedVisitor, PropertyInstanceType, StringLiteralType, TypeAliasType, TypeMapping,
TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, TypedDictParams,
VarianceInferable, declaration_type, infer_definition_types, todo_type,
};
use crate::{
Db, FxIndexMap, FxOrderSet, Program,
@ -303,14 +303,15 @@ impl<'db> GenericAlias<'db> {
)
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
self.specialization(db)
.find_legacy_typevars(db, binding_context, typevars);
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
pub(super) fn is_typed_dict(self, db: &'db dyn Db) -> bool {
@ -503,15 +504,18 @@ impl<'db> ClassType<'db> {
}
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self {
Self::NonGeneric(_) => {}
Self::Generic(generic) => generic.find_legacy_typevars(db, binding_context, typevars),
Self::Generic(generic) => {
generic.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
}

View file

@ -90,3 +90,9 @@ impl<Tag, T: Hash + Eq + Clone, R: Clone> CycleDetector<Tag, T, R> {
ret
}
}
impl<Tag, T: Hash + Eq + Clone, R: Default + Clone> Default for CycleDetector<Tag, T, R> {
fn default() -> Self {
CycleDetector::new(R::default())
}
}

View file

@ -78,9 +78,9 @@ use crate::types::signatures::{CallableSignature, Signature};
use crate::types::visitor::any_over_type;
use crate::types::{
BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, ClassType,
DeprecatedInstance, DynamicType, HasRelationToVisitor, IsEquivalentVisitor, KnownClass,
NormalizedVisitor, SpecialFormType, Truthiness, Type, TypeMapping, TypeRelation, UnionBuilder,
all_members, walk_type_mapping,
DeprecatedInstance, DynamicType, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, KnownClass, NormalizedVisitor, SpecialFormType, Truthiness, Type,
TypeMapping, TypeRelation, UnionBuilder, all_members, walk_type_mapping,
};
use crate::{Db, FxOrderSet, ModuleName, resolve_module};
@ -915,15 +915,16 @@ impl<'db> FunctionType<'db> {
self_signature.is_equivalent_to_impl(db, other_signature, visitor)
}
pub(crate) fn find_legacy_typevars(
pub(crate) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
let signatures = self.signature(db);
for signature in &signatures.overloads {
signature.find_legacy_typevars(db, binding_context, typevars);
signature.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}

View file

@ -15,10 +15,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::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, IsEquivalentVisitor,
KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeMapping,
TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance, UnionType,
binding_type, declaration_type,
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor,
Type, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
UnionType, binding_type, declaration_type,
};
use crate::{Db, FxOrderSet};
@ -888,14 +888,15 @@ impl<'db> Specialization<'db> {
result
}
pub(crate) fn find_legacy_typevars(
pub(crate) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for ty in self.types(db) {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
// A tuple's specialization will include all of its element types, so we don't need to also
// look in `self.tuple`.

View file

@ -12,9 +12,9 @@ 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::{
ApplyTypeMappingVisitor, ClassBase, HasRelationToVisitor, IsDisjointVisitor,
IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation,
VarianceInferable,
ApplyTypeMappingVisitor, ClassBase, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsDisjointVisitor, IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, TypeMapping,
TypeRelation, VarianceInferable,
};
use crate::{Db, FxOrderSet};
@ -380,18 +380,19 @@ impl<'db> NominalInstanceType<'db> {
}
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self.0 {
NominalInstanceInner::ExactTuple(tuple) => {
tuple.find_legacy_typevars(db, binding_context, typevars);
tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
NominalInstanceInner::NonTuple(class) => {
class.find_legacy_typevars(db, binding_context, typevars);
class.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
}
@ -614,18 +615,19 @@ impl<'db> ProtocolInstanceType<'db> {
}
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self.inner {
Protocol::FromClass(class) => {
class.find_legacy_typevars(db, binding_context, typevars);
class.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Protocol::Synthesized(synthesized) => {
synthesized.find_legacy_typevars(db, binding_context, typevars);
synthesized.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
}
@ -679,8 +681,8 @@ mod synthesized_protocol {
use crate::semantic_index::definition::Definition;
use crate::types::protocol_class::ProtocolInterface;
use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, MaterializationKind, NormalizedVisitor,
TypeMapping, TypeVarVariance, VarianceInferable,
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor,
MaterializationKind, NormalizedVisitor, TypeMapping, TypeVarVariance, VarianceInferable,
};
use crate::{Db, FxOrderSet};
@ -724,13 +726,15 @@ mod synthesized_protocol {
Self(self.0.specialized_and_normalized(db, type_mapping))
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
self.0.find_legacy_typevars(db, binding_context, typevars);
self.0
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
pub(in crate::types) fn interface(self) -> ProtocolInterface<'db> {

View file

@ -17,10 +17,10 @@ use crate::{
place::{Boundness, Place, PlaceAndQualifiers, place_from_bindings, place_from_declarations},
semantic_index::{definition::Definition, use_def_map},
types::{
BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, HasRelationToVisitor,
IsDisjointVisitor, KnownFunction, MaterializationKind, NormalizedVisitor,
PropertyInstanceType, Signature, Type, TypeMapping, TypeQualifiers, TypeRelation,
VarianceInferable,
BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, FindLegacyTypeVarsVisitor,
HasRelationToVisitor, IsDisjointVisitor, KnownFunction, MaterializationKind,
NormalizedVisitor, PropertyInstanceType, Signature, Type, TypeMapping, TypeQualifiers,
TypeRelation, VarianceInferable,
constraints::{Constraints, IteratorConstraintsExtension},
signatures::{Parameter, Parameters},
},
@ -289,14 +289,15 @@ impl<'db> ProtocolInterface<'db> {
)
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for data in self.inner(db).values() {
data.find_legacy_typevars(db, binding_context, typevars);
data.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
@ -360,14 +361,15 @@ impl<'db> ProtocolMemberData<'db> {
}
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
self.kind
.find_legacy_typevars(db, binding_context, typevars);
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
fn materialize(&self, db: &'db dyn Db, materialization_kind: MaterializationKind) -> Self {
@ -456,18 +458,19 @@ impl<'db> ProtocolMemberKind<'db> {
}
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self {
ProtocolMemberKind::Method(callable) => {
callable.find_legacy_typevars(db, binding_context, typevars);
callable.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
ProtocolMemberKind::Property(property) => {
property.find_legacy_typevars(db, binding_context, typevars);
property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
ProtocolMemberKind::Other(ty) => {
ty.find_legacy_typevars(db, binding_context, typevars);

View file

@ -20,9 +20,9 @@ use crate::semantic_index::definition::Definition;
use crate::types::constraints::{Constraints, IteratorConstraintsExtension};
use crate::types::generics::{GenericContext, walk_generic_context};
use crate::types::{
BindingContext, BoundTypeVarInstance, HasRelationToVisitor, IsEquivalentVisitor, KnownClass,
MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation, VarianceInferable,
todo_type,
BindingContext, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, KnownClass, MaterializationKind, NormalizedVisitor, TypeMapping,
TypeRelation, VarianceInferable, todo_type,
};
use crate::{Db, FxOrderSet};
use ruff_python_ast::{self as ast, name::Name};
@ -94,14 +94,15 @@ impl<'db> CallableSignature<'db> {
)
}
pub(crate) fn find_legacy_typevars(
pub(crate) fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for signature in &self.overloads {
signature.find_legacy_typevars(db, binding_context, typevars);
signature.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
@ -467,22 +468,23 @@ impl<'db> Signature<'db> {
}
}
pub(crate) fn find_legacy_typevars(
pub(crate) fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for param in &self.parameters {
if let Some(ty) = param.annotated_type() {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
if let Some(ty) = param.default_type() {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
if let Some(ty) = self.return_ty {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}

View file

@ -3,9 +3,10 @@ use crate::semantic_index::definition::Definition;
use crate::types::constraints::Constraints;
use crate::types::variance::VarianceInferable;
use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType, HasRelationToVisitor,
IsDisjointVisitor, KnownClass, MaterializationKind, MemberLookupPolicy, NormalizedVisitor,
SpecialFormType, Type, TypeMapping, TypeRelation,
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType,
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, KnownClass,
MaterializationKind, MemberLookupPolicy, NormalizedVisitor, SpecialFormType, Type, TypeMapping,
TypeRelation,
};
use crate::{Db, FxOrderSet};
@ -111,15 +112,16 @@ impl<'db> SubclassOfType<'db> {
}
}
pub(super) fn find_legacy_typevars(
pub(super) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self.subclass_of {
SubclassOfInner::Class(class) => {
class.find_legacy_typevars(db, binding_context, typevars);
class.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
SubclassOfInner::Dynamic(_) => {}
}

View file

@ -26,9 +26,9 @@ use crate::types::Truthiness;
use crate::types::class::{ClassType, KnownClass};
use crate::types::constraints::{Constraints, IteratorConstraintsExtension};
use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, IsDisjointVisitor,
IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, Type, TypeMapping, TypeRelation,
UnionBuilder, UnionType,
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsDisjointVisitor, IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, Type,
TypeMapping, TypeRelation, UnionBuilder, UnionType,
};
use crate::util::subscript::{Nth, OutOfBoundsError, PyIndex, PySlice, StepSizeZeroError};
use crate::{Db, FxOrderSet, Program};
@ -250,14 +250,15 @@ impl<'db> TupleType<'db> {
)
}
pub(crate) fn find_legacy_typevars(
pub(crate) fn find_legacy_typevars_impl(
self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
self.tuple(db)
.find_legacy_typevars(db, binding_context, typevars);
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
pub(crate) fn has_relation_to_impl<C: Constraints<'db>>(
@ -414,14 +415,15 @@ impl<'db> FixedLengthTuple<Type<'db>> {
)
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for ty in &self.0 {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
@ -745,19 +747,20 @@ impl<'db> VariableLengthTuple<Type<'db>> {
)
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
for ty in &self.prefix {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
self.variable
.find_legacy_typevars(db, binding_context, typevars);
.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
for ty in &self.suffix {
ty.find_legacy_typevars(db, binding_context, typevars);
ty.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
@ -1099,15 +1102,20 @@ impl<'db> Tuple<Type<'db>> {
}
}
fn find_legacy_typevars(
fn find_legacy_typevars_impl(
&self,
db: &'db dyn Db,
binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) {
match self {
Tuple::Fixed(tuple) => tuple.find_legacy_typevars(db, binding_context, typevars),
Tuple::Variable(tuple) => tuple.find_legacy_typevars(db, binding_context, typevars),
Tuple::Fixed(tuple) => {
tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Tuple::Variable(tuple) => {
tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
}
}