[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 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 ### Mutually recursive
```py ```py

View file

@ -19,7 +19,7 @@ use ruff_text_size::{Ranged, TextRange};
use type_ordering::union_or_intersection_elements_ordering; use type_ordering::union_or_intersection_elements_ordering;
pub(crate) use self::builder::{IntersectionBuilder, UnionBuilder}; 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 use self::diagnostic::TypeCheckDiagnostics;
pub(crate) use self::diagnostic::register_lints; pub(crate) use self::diagnostic::register_lints;
pub(crate) use self::infer::{ 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) type IsEquivalentVisitor<'db, C> = PairVisitor<'db, IsEquivalent, C>;
pub(crate) struct IsEquivalent; 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. /// A [`TypeTransformer`] that is used in `normalized` methods.
pub(crate) type NormalizedVisitor<'db> = TypeTransformer<'db, Normalized>; pub(crate) type NormalizedVisitor<'db> = TypeTransformer<'db, Normalized>;
pub(crate) struct Normalized; pub(crate) struct Normalized;
@ -503,17 +507,18 @@ impl<'db> PropertyInstanceType<'db> {
) )
} }
fn find_legacy_typevars( fn find_legacy_typevars_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
if let Some(ty) = self.getter(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) { 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, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'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 { match self {
Type::NonInferableTypeVar(bound_typevar) | Type::TypeVar(bound_typevar) => { Type::NonInferableTypeVar(bound_typevar) | Type::TypeVar(bound_typevar) => {
@ -6171,80 +6191,94 @@ impl<'db> Type<'db> {
} }
Type::FunctionLiteral(function) => { Type::FunctionLiteral(function) => {
function.find_legacy_typevars(db, binding_context, typevars); function.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::BoundMethod(method) => { Type::BoundMethod(method) => {
method method.self_instance(db).find_legacy_typevars_impl(
.self_instance(db) db,
.find_legacy_typevars(db, binding_context, typevars); binding_context,
method typevars,
.function(db) visitor,
.find_legacy_typevars(db, binding_context, typevars); );
method.function(db).find_legacy_typevars_impl(
db,
binding_context,
typevars,
visitor,
);
} }
Type::MethodWrapper( Type::MethodWrapper(
MethodWrapperKind::FunctionTypeDunderGet(function) MethodWrapperKind::FunctionTypeDunderGet(function)
| MethodWrapperKind::FunctionTypeDunderCall(function), | MethodWrapperKind::FunctionTypeDunderCall(function),
) => { ) => {
function.find_legacy_typevars(db, binding_context, typevars); function.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::MethodWrapper( Type::MethodWrapper(
MethodWrapperKind::PropertyDunderGet(property) MethodWrapperKind::PropertyDunderGet(property)
| MethodWrapperKind::PropertyDunderSet(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) => { Type::Callable(callable) => {
callable.find_legacy_typevars(db, binding_context, typevars); callable.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::PropertyInstance(property) => { Type::PropertyInstance(property) => {
property.find_legacy_typevars(db, binding_context, typevars); property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::Union(union) => { Type::Union(union) => {
for element in union.elements(db) { 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) => { Type::Intersection(intersection) => {
for positive in intersection.positive(db) { 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) { 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) => { Type::GenericAlias(alias) => {
alias.find_legacy_typevars(db, binding_context, typevars); alias.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::NominalInstance(instance) => { Type::NominalInstance(instance) => {
instance.find_legacy_typevars(db, binding_context, typevars); instance.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::ProtocolInstance(instance) => { 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) => { 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::TypeIs(type_is) => {
type_is type_is.return_type(db).find_legacy_typevars_impl(
.return_type(db) db,
.find_legacy_typevars(db, binding_context, typevars); binding_context,
typevars,
visitor,
);
} }
Type::TypeAlias(alias) => { Type::TypeAlias(alias) => {
alias visitor.visit(self, || {
.value_type(db) alias.value_type(db).find_legacy_typevars_impl(
.find_legacy_typevars(db, binding_context, typevars); db,
binding_context,
typevars,
visitor,
);
});
} }
Type::Dynamic(_) Type::Dynamic(_)
@ -8907,14 +8941,15 @@ impl<'db> CallableType<'db> {
) )
} }
fn find_legacy_typevars( fn find_legacy_typevars_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
self.signatures(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. /// 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::typed_dict::typed_dict_params_from_class_def;
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, Binding, BoundSuperError, BoundSuperType, CallableType, ApplyTypeMappingVisitor, Binding, BoundSuperError, BoundSuperType, CallableType,
DataclassParams, DeprecatedInstance, HasRelationToVisitor, IsEquivalentVisitor, DataclassParams, DeprecatedInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
KnownInstanceType, ManualPEP695TypeAliasType, MaterializationKind, NormalizedVisitor, IsEquivalentVisitor, KnownInstanceType, ManualPEP695TypeAliasType, MaterializationKind,
PropertyInstanceType, StringLiteralType, TypeAliasType, TypeMapping, TypeRelation, NormalizedVisitor, PropertyInstanceType, StringLiteralType, TypeAliasType, TypeMapping,
TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, TypedDictParams, VarianceInferable, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, TypedDictParams,
declaration_type, infer_definition_types, todo_type, VarianceInferable, declaration_type, infer_definition_types, todo_type,
}; };
use crate::{ use crate::{
Db, FxIndexMap, FxOrderSet, Program, 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
self.specialization(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 { 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self { match self {
Self::NonGeneric(_) => {} 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 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::visitor::any_over_type;
use crate::types::{ use crate::types::{
BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, ClassType, BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, ClassType,
DeprecatedInstance, DynamicType, HasRelationToVisitor, IsEquivalentVisitor, KnownClass, DeprecatedInstance, DynamicType, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
NormalizedVisitor, SpecialFormType, Truthiness, Type, TypeMapping, TypeRelation, UnionBuilder, IsEquivalentVisitor, KnownClass, NormalizedVisitor, SpecialFormType, Truthiness, Type,
all_members, walk_type_mapping, TypeMapping, TypeRelation, UnionBuilder, all_members, walk_type_mapping,
}; };
use crate::{Db, FxOrderSet, ModuleName, resolve_module}; 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) self_signature.is_equivalent_to_impl(db, other_signature, visitor)
} }
pub(crate) fn find_legacy_typevars( pub(crate) fn find_legacy_typevars_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
let signatures = self.signature(db); let signatures = self.signature(db);
for signature in &signatures.overloads { 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::signatures::{Parameter, Parameters, Signature};
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type}; use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, IsEquivalentVisitor, ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeMapping, IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor,
TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance, UnionType, Type, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
binding_type, declaration_type, UnionType, binding_type, declaration_type,
}; };
use crate::{Db, FxOrderSet}; use crate::{Db, FxOrderSet};
@ -888,14 +888,15 @@ impl<'db> Specialization<'db> {
result result
} }
pub(crate) fn find_legacy_typevars( pub(crate) fn find_legacy_typevars_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for ty in self.types(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 // A tuple's specialization will include all of its element types, so we don't need to also
// look in `self.tuple`. // 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::protocol_class::walk_protocol_interface;
use crate::types::tuple::{TupleSpec, TupleType}; use crate::types::tuple::{TupleSpec, TupleType};
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, ClassBase, HasRelationToVisitor, IsDisjointVisitor, ApplyTypeMappingVisitor, ClassBase, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation, IsDisjointVisitor, IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, TypeMapping,
VarianceInferable, TypeRelation, VarianceInferable,
}; };
use crate::{Db, FxOrderSet}; 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self.0 { match self.0 {
NominalInstanceInner::ExactTuple(tuple) => { NominalInstanceInner::ExactTuple(tuple) => {
tuple.find_legacy_typevars(db, binding_context, typevars); tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
NominalInstanceInner::NonTuple(class) => { 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self.inner { match self.inner {
Protocol::FromClass(class) => { Protocol::FromClass(class) => {
class.find_legacy_typevars(db, binding_context, typevars); class.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Protocol::Synthesized(synthesized) => { 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::semantic_index::definition::Definition;
use crate::types::protocol_class::ProtocolInterface; use crate::types::protocol_class::ProtocolInterface;
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, MaterializationKind, NormalizedVisitor, ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor,
TypeMapping, TypeVarVariance, VarianceInferable, MaterializationKind, NormalizedVisitor, TypeMapping, TypeVarVariance, VarianceInferable,
}; };
use crate::{Db, FxOrderSet}; use crate::{Db, FxOrderSet};
@ -724,13 +726,15 @@ mod synthesized_protocol {
Self(self.0.specialized_and_normalized(db, type_mapping)) Self(self.0.specialized_and_normalized(db, type_mapping))
} }
pub(super) fn find_legacy_typevars( pub(super) fn find_legacy_typevars_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'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> { 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}, place::{Boundness, Place, PlaceAndQualifiers, place_from_bindings, place_from_declarations},
semantic_index::{definition::Definition, use_def_map}, semantic_index::{definition::Definition, use_def_map},
types::{ types::{
BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, HasRelationToVisitor, BoundTypeVarInstance, CallableType, ClassBase, ClassLiteral, FindLegacyTypeVarsVisitor,
IsDisjointVisitor, KnownFunction, MaterializationKind, NormalizedVisitor, HasRelationToVisitor, IsDisjointVisitor, KnownFunction, MaterializationKind,
PropertyInstanceType, Signature, Type, TypeMapping, TypeQualifiers, TypeRelation, NormalizedVisitor, PropertyInstanceType, Signature, Type, TypeMapping, TypeQualifiers,
VarianceInferable, TypeRelation, VarianceInferable,
constraints::{Constraints, IteratorConstraintsExtension}, constraints::{Constraints, IteratorConstraintsExtension},
signatures::{Parameter, Parameters}, 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for data in self.inner(db).values() { 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
self.kind 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 { 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self { match self {
ProtocolMemberKind::Method(callable) => { ProtocolMemberKind::Method(callable) => {
callable.find_legacy_typevars(db, binding_context, typevars); callable.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
ProtocolMemberKind::Property(property) => { ProtocolMemberKind::Property(property) => {
property.find_legacy_typevars(db, binding_context, typevars); property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
ProtocolMemberKind::Other(ty) => { ProtocolMemberKind::Other(ty) => {
ty.find_legacy_typevars(db, binding_context, typevars); 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::constraints::{Constraints, IteratorConstraintsExtension};
use crate::types::generics::{GenericContext, walk_generic_context}; use crate::types::generics::{GenericContext, walk_generic_context};
use crate::types::{ use crate::types::{
BindingContext, BoundTypeVarInstance, HasRelationToVisitor, IsEquivalentVisitor, KnownClass, BindingContext, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation, VarianceInferable, IsEquivalentVisitor, KnownClass, MaterializationKind, NormalizedVisitor, TypeMapping,
todo_type, TypeRelation, VarianceInferable, todo_type,
}; };
use crate::{Db, FxOrderSet}; use crate::{Db, FxOrderSet};
use ruff_python_ast::{self as ast, name::Name}; 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for signature in &self.overloads { 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for param in &self.parameters { for param in &self.parameters {
if let Some(ty) = param.annotated_type() { 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() { 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 { 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::constraints::Constraints;
use crate::types::variance::VarianceInferable; use crate::types::variance::VarianceInferable;
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType, HasRelationToVisitor, ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType,
IsDisjointVisitor, KnownClass, MaterializationKind, MemberLookupPolicy, NormalizedVisitor, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, KnownClass,
SpecialFormType, Type, TypeMapping, TypeRelation, MaterializationKind, MemberLookupPolicy, NormalizedVisitor, SpecialFormType, Type, TypeMapping,
TypeRelation,
}; };
use crate::{Db, FxOrderSet}; 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self.subclass_of { match self.subclass_of {
SubclassOfInner::Class(class) => { SubclassOfInner::Class(class) => {
class.find_legacy_typevars(db, binding_context, typevars); class.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
SubclassOfInner::Dynamic(_) => {} SubclassOfInner::Dynamic(_) => {}
} }

View file

@ -26,9 +26,9 @@ use crate::types::Truthiness;
use crate::types::class::{ClassType, KnownClass}; use crate::types::class::{ClassType, KnownClass};
use crate::types::constraints::{Constraints, IteratorConstraintsExtension}; use crate::types::constraints::{Constraints, IteratorConstraintsExtension};
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarInstance, HasRelationToVisitor, IsDisjointVisitor, ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, Type, TypeMapping, TypeRelation, IsDisjointVisitor, IsEquivalentVisitor, MaterializationKind, NormalizedVisitor, Type,
UnionBuilder, UnionType, TypeMapping, TypeRelation, UnionBuilder, UnionType,
}; };
use crate::util::subscript::{Nth, OutOfBoundsError, PyIndex, PySlice, StepSizeZeroError}; use crate::util::subscript::{Nth, OutOfBoundsError, PyIndex, PySlice, StepSizeZeroError};
use crate::{Db, FxOrderSet, Program}; 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, self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
self.tuple(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>>( 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for ty in &self.0 { 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
for ty in &self.prefix { 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 self.variable
.find_legacy_typevars(db, binding_context, typevars); .find_legacy_typevars_impl(db, binding_context, typevars, visitor);
for ty in &self.suffix { 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, &self,
db: &'db dyn Db, db: &'db dyn Db,
binding_context: Option<Definition<'db>>, binding_context: Option<Definition<'db>>,
typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>, typevars: &mut FxOrderSet<BoundTypeVarInstance<'db>>,
visitor: &FindLegacyTypeVarsVisitor<'db>,
) { ) {
match self { match self {
Tuple::Fixed(tuple) => tuple.find_legacy_typevars(db, binding_context, typevars), Tuple::Fixed(tuple) => {
Tuple::Variable(tuple) => tuple.find_legacy_typevars(db, binding_context, typevars), tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
Tuple::Variable(tuple) => {
tuple.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
}
} }
} }