@@ -65,6 +65,7 @@ use crate::types::signatures::{Parameter, ParameterForm, Parameters, walk_signat
6565use crate :: types:: tuple:: TupleSpec ;
6666pub ( crate ) use crate :: types:: typed_dict:: { TypedDictParams , TypedDictType , walk_typed_dict_type} ;
6767use crate :: types:: variance:: { TypeVarVariance , VarianceInferable } ;
68+ use crate :: types:: visitor:: any_over_type;
6869use crate :: unpack:: EvaluationMode ;
6970pub use crate :: util:: diagnostics:: add_inferred_python_version_hint_to_diagnostic;
7071use crate :: { Db , FxOrderSet , Module , Program } ;
@@ -221,10 +222,6 @@ pub(crate) struct TryBool;
221222pub ( crate ) type NormalizedVisitor < ' db > = TypeTransformer < ' db , Normalized > ;
222223pub ( crate ) struct Normalized ;
223224
224- /// A [`CycleDetector`] that is used in `has_divergent_type` methods.
225- pub ( crate ) type HasDivergentTypeVisitor < ' db > = CycleDetector < HasDivergentType , Type < ' db > , bool > ;
226- pub ( crate ) struct HasDivergentType ;
227-
228225/// How a generic type has been specialized.
229226///
230227/// This matters only if there is at least one invariant type parameter.
@@ -591,19 +588,6 @@ impl<'db> PropertyInstanceType<'db> {
591588
592589 getter_equivalence. and ( db, setter_equivalence)
593590 }
594-
595- fn has_divergent_type_impl (
596- self ,
597- db : & ' db dyn Db ,
598- div : Type < ' db > ,
599- visitor : & HasDivergentTypeVisitor < ' db > ,
600- ) -> bool {
601- self . getter ( db)
602- . is_some_and ( |ty| ty. has_divergent_type_impl ( db, div, visitor) )
603- || self
604- . setter ( db)
605- . is_some_and ( |ty| ty. has_divergent_type_impl ( db, div, visitor) )
606- }
607591}
608592
609593bitflags ! {
@@ -6512,77 +6496,7 @@ impl<'db> Type<'db> {
65126496 }
65136497
65146498 pub ( super ) fn has_divergent_type ( self , db : & ' db dyn Db , div : Type < ' db > ) -> bool {
6515- self . has_divergent_type_impl ( db, div, & HasDivergentTypeVisitor :: new ( false ) )
6516- }
6517-
6518- pub ( super ) fn has_divergent_type_impl (
6519- self ,
6520- db : & ' db dyn Db ,
6521- div : Type < ' db > ,
6522- visitor : & HasDivergentTypeVisitor < ' db > ,
6523- ) -> bool {
6524- // We don't use `any_over_type` here because we don't need/want to descend into lazy
6525- // parts of types (typevar bounds/constraints, type alias values, etc) here. If it's a lazy
6526- // aspect of the type, it won't cause a query cycle in type inference, and we shouldn't
6527- // trigger unnecessary inference of it. (TODO: bounds/constraints of legacy typevars aren't
6528- // yet lazy, but they should be.)
6529- match self {
6530- Type :: Dynamic ( DynamicType :: Divergent ( _) ) => self == div,
6531- Type :: Union ( union) => union. has_divergent_type_impl ( db, div, visitor) ,
6532- Type :: Intersection ( intersection) => {
6533- intersection. has_divergent_type_impl ( db, div, visitor)
6534- }
6535- Type :: GenericAlias ( alias) => visitor. visit ( self , || {
6536- alias
6537- . specialization ( db)
6538- . has_divergent_type_impl ( db, div, visitor)
6539- } ) ,
6540- Type :: NominalInstance ( instance) => visitor. visit ( self , || {
6541- instance. class ( db) . has_divergent_type_impl ( db, div, visitor)
6542- } ) ,
6543- Type :: Callable ( callable) => {
6544- visitor. visit ( self , || callable. has_divergent_type_impl ( db, div, visitor) )
6545- }
6546- Type :: ProtocolInstance ( protocol) => {
6547- visitor. visit ( self , || protocol. has_divergent_type_impl ( db, div, visitor) )
6548- }
6549- Type :: PropertyInstance ( property) => property. has_divergent_type_impl ( db, div, visitor) ,
6550- Type :: TypeIs ( type_is) => type_is
6551- . return_type ( db)
6552- . has_divergent_type_impl ( db, div, visitor) ,
6553- Type :: SubclassOf ( subclass_of) => visitor. visit ( self , || {
6554- subclass_of. has_divergent_type_impl ( db, div, visitor)
6555- } ) ,
6556- Type :: TypedDict ( typed_dict) => visitor. visit ( self , || {
6557- typed_dict
6558- . defining_class ( )
6559- . has_divergent_type_impl ( db, div, visitor)
6560- } ) ,
6561- Type :: Never
6562- | Type :: AlwaysTruthy
6563- | Type :: AlwaysFalsy
6564- | Type :: WrapperDescriptor ( _)
6565- | Type :: DataclassDecorator ( _)
6566- | Type :: DataclassTransformer ( _)
6567- | Type :: ModuleLiteral ( _)
6568- | Type :: ClassLiteral ( _)
6569- | Type :: IntLiteral ( _)
6570- | Type :: BooleanLiteral ( _)
6571- | Type :: LiteralString
6572- | Type :: StringLiteral ( _)
6573- | Type :: BytesLiteral ( _)
6574- | Type :: EnumLiteral ( _)
6575- | Type :: BoundSuper ( _)
6576- | Type :: SpecialForm ( _)
6577- | Type :: KnownInstance ( _)
6578- | Type :: NonInferableTypeVar ( _)
6579- | Type :: TypeVar ( _)
6580- | Type :: FunctionLiteral ( _)
6581- | Type :: KnownBoundMethod ( _)
6582- | Type :: BoundMethod ( _)
6583- | Type :: Dynamic ( _)
6584- | Type :: TypeAlias ( _) => false ,
6585- }
6499+ any_over_type ( db, self , & |ty| ty == div, false )
65866500 }
65876501}
65886502
@@ -7528,10 +7442,27 @@ fn walk_type_var_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
75287442 typevar : TypeVarInstance < ' db > ,
75297443 visitor : & V ,
75307444) {
7531- if let Some ( bounds) = typevar. bound_or_constraints ( db) {
7532- walk_type_var_bounds ( db, bounds, visitor) ;
7445+ if let Some ( bound_or_constraints) = if visitor. should_visit_lazy_type_attributes ( ) {
7446+ typevar. bound_or_constraints ( db)
7447+ } else {
7448+ match typevar. _bound_or_constraints ( db) {
7449+ _ if visitor. should_visit_lazy_type_attributes ( ) => typevar. bound_or_constraints ( db) ,
7450+ Some ( TypeVarBoundOrConstraintsEvaluation :: Eager ( bound_or_constraints) ) => {
7451+ Some ( bound_or_constraints)
7452+ }
7453+ _ => None ,
7454+ }
7455+ } {
7456+ walk_type_var_bounds ( db, bound_or_constraints, visitor) ;
75337457 }
7534- if let Some ( default_type) = typevar. default_type ( db) {
7458+ if let Some ( default_type) = if visitor. should_visit_lazy_type_attributes ( ) {
7459+ typevar. default_type ( db)
7460+ } else {
7461+ match typevar. _default ( db) {
7462+ Some ( TypeVarDefaultEvaluation :: Eager ( default_type) ) => Some ( default_type) ,
7463+ _ => None ,
7464+ }
7465+ } {
75357466 visitor. visit_type ( db, default_type) ;
75367467 }
75377468}
@@ -9314,16 +9245,6 @@ impl<'db> CallableType<'db> {
93149245 . is_equivalent_to_impl ( db, other. signatures ( db) , visitor)
93159246 } )
93169247 }
9317-
9318- fn has_divergent_type_impl (
9319- self ,
9320- db : & ' db dyn Db ,
9321- div : Type < ' db > ,
9322- visitor : & HasDivergentTypeVisitor < ' db > ,
9323- ) -> bool {
9324- self . signatures ( db)
9325- . has_divergent_type_impl ( db, div, visitor)
9326- }
93279248}
93289249
93299250/// Represents a specific instance of a bound method type for a builtin class.
@@ -9970,6 +9891,9 @@ fn walk_type_alias_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
99709891 type_alias : TypeAliasType < ' db > ,
99719892 visitor : & V ,
99729893) {
9894+ if !visitor. should_visit_lazy_type_attributes ( ) {
9895+ return ;
9896+ }
99739897 match type_alias {
99749898 TypeAliasType :: PEP695 ( type_alias) => {
99759899 walk_pep_695_type_alias ( db, type_alias, visitor) ;
@@ -10298,17 +10222,6 @@ impl<'db> UnionType<'db> {
1029810222
1029910223 ConstraintSet :: from ( sorted_self == other. normalized ( db) )
1030010224 }
10301-
10302- fn has_divergent_type_impl (
10303- self ,
10304- db : & ' db dyn Db ,
10305- div : Type < ' db > ,
10306- visitor : & HasDivergentTypeVisitor < ' db > ,
10307- ) -> bool {
10308- self . elements ( db)
10309- . iter ( )
10310- . any ( |ty| ty. has_divergent_type_impl ( db, div, visitor) )
10311- }
1031210225}
1031310226
1031410227#[ salsa:: interned( debug, heap_size=IntersectionType :: heap_size) ]
@@ -10524,21 +10437,6 @@ impl<'db> IntersectionType<'db> {
1052410437 ruff_memory_usage:: order_set_heap_size ( positive)
1052510438 + ruff_memory_usage:: order_set_heap_size ( negative)
1052610439 }
10527-
10528- fn has_divergent_type_impl (
10529- self ,
10530- db : & ' db dyn Db ,
10531- div : Type < ' db > ,
10532- visitor : & HasDivergentTypeVisitor < ' db > ,
10533- ) -> bool {
10534- self . positive ( db)
10535- . iter ( )
10536- . any ( |ty| ty. has_divergent_type_impl ( db, div, visitor) )
10537- || self
10538- . negative ( db)
10539- . iter ( )
10540- . any ( |ty| ty. has_divergent_type_impl ( db, div, visitor) )
10541- }
1054210440}
1054310441
1054410442/// # Ordering
0 commit comments