Skip to content

Commit 814c42d

Browse files
committed
use any_over_type again
1 parent b32fc8b commit 814c42d

File tree

12 files changed

+108
-275
lines changed

12 files changed

+108
-275
lines changed

crates/ty_python_semantic/src/types.rs

Lines changed: 25 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use crate::types::signatures::{Parameter, ParameterForm, Parameters, walk_signat
6565
use crate::types::tuple::TupleSpec;
6666
pub(crate) use crate::types::typed_dict::{TypedDictParams, TypedDictType, walk_typed_dict_type};
6767
use crate::types::variance::{TypeVarVariance, VarianceInferable};
68+
use crate::types::visitor::any_over_type;
6869
use crate::unpack::EvaluationMode;
6970
pub use crate::util::diagnostics::add_inferred_python_version_hint_to_diagnostic;
7071
use crate::{Db, FxOrderSet, Module, Program};
@@ -221,10 +222,6 @@ pub(crate) struct TryBool;
221222
pub(crate) type NormalizedVisitor<'db> = TypeTransformer<'db, Normalized>;
222223
pub(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

609593
bitflags! {
@@ -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

crates/ty_python_semantic/src/types/class.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ use crate::types::tuple::{TupleSpec, TupleType};
2626
use crate::types::typed_dict::typed_dict_params_from_class_def;
2727
use crate::types::{
2828
ApplyTypeMappingVisitor, Binding, BoundSuperError, BoundSuperType, CallableType,
29-
DataclassParams, DeprecatedInstance, FindLegacyTypeVarsVisitor, HasDivergentTypeVisitor,
30-
HasRelationToVisitor, IsEquivalentVisitor, KnownInstanceType, ManualPEP695TypeAliasType,
31-
MaterializationKind, NormalizedVisitor, PropertyInstanceType, StringLiteralType, TypeAliasType,
32-
TypeContext, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance,
33-
TypeVarKind, TypedDictParams, UnionBuilder, VarianceInferable, declaration_type,
34-
determine_upper_bound, infer_definition_types,
29+
DataclassParams, DeprecatedInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
30+
IsEquivalentVisitor, KnownInstanceType, ManualPEP695TypeAliasType, MaterializationKind,
31+
NormalizedVisitor, PropertyInstanceType, StringLiteralType, TypeAliasType, TypeContext,
32+
TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind,
33+
TypedDictParams, UnionBuilder, VarianceInferable, declaration_type, determine_upper_bound,
34+
infer_definition_types,
3535
};
3636
use crate::{
3737
Db, FxIndexMap, FxOrderSet, Program,
@@ -615,20 +615,6 @@ impl<'db> ClassType<'db> {
615615
}
616616
}
617617

618-
pub(super) fn has_divergent_type_impl(
619-
self,
620-
db: &'db dyn Db,
621-
div: Type<'db>,
622-
visitor: &HasDivergentTypeVisitor<'db>,
623-
) -> bool {
624-
match self {
625-
ClassType::NonGeneric(_) => false,
626-
ClassType::Generic(generic) => generic
627-
.specialization(db)
628-
.has_divergent_type_impl(db, div, visitor),
629-
}
630-
}
631-
632618
/// Return the metaclass of this class, or `type[Unknown]` if the metaclass cannot be inferred.
633619
pub(super) fn metaclass(self, db: &'db dyn Db) -> Type<'db> {
634620
let (class_literal, specialization) = self.class_literal(db);

crates/ty_python_semantic/src/types/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,8 +1499,8 @@ impl KnownFunction {
14991499
let contains_unknown_or_todo =
15001500
|ty| matches!(ty, Type::Dynamic(dynamic) if dynamic != DynamicType::Any);
15011501
if source_type.is_equivalent_to(db, *casted_type)
1502-
&& !any_over_type(db, *source_type, &contains_unknown_or_todo)
1503-
&& !any_over_type(db, *casted_type, &contains_unknown_or_todo)
1502+
&& !any_over_type(db, *source_type, &contains_unknown_or_todo, true)
1503+
&& !any_over_type(db, *casted_type, &contains_unknown_or_todo, true)
15041504
{
15051505
if let Some(builder) = context.report_lint(&REDUNDANT_CAST, call_expression) {
15061506
builder.into_diagnostic(format_args!(

crates/ty_python_semantic/src/types/generics.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ use crate::types::instance::{Protocol, ProtocolInstanceType};
1616
use crate::types::signatures::{Parameter, Parameters, Signature};
1717
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
1818
use crate::types::{
19-
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor,
20-
HasDivergentTypeVisitor, HasRelationToVisitor, IsEquivalentVisitor, KnownClass,
21-
KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeMapping, TypeRelation,
22-
TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance, UnionType, binding_type,
23-
declaration_type,
19+
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
20+
IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor,
21+
Type, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
22+
UnionType, binding_type, declaration_type,
2423
};
2524
use crate::{Db, FxOrderSet};
2625

@@ -927,20 +926,6 @@ impl<'db> Specialization<'db> {
927926
// A tuple's specialization will include all of its element types, so we don't need to also
928927
// look in `self.tuple`.
929928
}
930-
931-
pub(super) fn has_divergent_type_impl(
932-
self,
933-
db: &'db dyn Db,
934-
div: Type<'db>,
935-
visitor: &HasDivergentTypeVisitor<'db>,
936-
) -> bool {
937-
self.types(db)
938-
.iter()
939-
.any(|ty| ty.has_divergent_type_impl(db, div, visitor))
940-
|| self
941-
.tuple_inner(db)
942-
.is_some_and(|tuple| tuple.has_divergent_type_impl(db, div, visitor))
943-
}
944929
}
945930

946931
/// A mapping between type variables and types.

crates/ty_python_semantic/src/types/infer/builder.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8785,14 +8785,19 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
87858785
*typevar,
87868786
)
87878787
.ok_or(GenericContextError::InvalidArgument)
8788-
} else if any_over_type(self.db(), *typevar, &|ty| match ty {
8789-
Type::Dynamic(DynamicType::TodoUnpack) => true,
8790-
Type::NominalInstance(nominal) => matches!(
8791-
nominal.known_class(self.db()),
8792-
Some(KnownClass::TypeVarTuple | KnownClass::ParamSpec)
8793-
),
8794-
_ => false,
8795-
}) {
8788+
} else if any_over_type(
8789+
self.db(),
8790+
*typevar,
8791+
&|ty| match ty {
8792+
Type::Dynamic(DynamicType::TodoUnpack) => true,
8793+
Type::NominalInstance(nominal) => matches!(
8794+
nominal.known_class(self.db()),
8795+
Some(KnownClass::TypeVarTuple | KnownClass::ParamSpec)
8796+
),
8797+
_ => false,
8798+
},
8799+
true,
8800+
) {
87968801
Err(GenericContextError::NotYetSupported)
87978802
} else {
87988803
if let Some(builder) =

crates/ty_python_semantic/src/types/infer/builder/type_expression.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,13 +1522,18 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
15221522
// `Callable[]`.
15231523
return None;
15241524
}
1525-
if any_over_type(self.db(), self.infer_name_load(name), &|ty| match ty {
1526-
Type::Dynamic(DynamicType::TodoPEP695ParamSpec) => true,
1527-
Type::NominalInstance(nominal) => {
1528-
nominal.has_known_class(self.db(), KnownClass::ParamSpec)
1529-
}
1530-
_ => false,
1531-
}) {
1525+
if any_over_type(
1526+
self.db(),
1527+
self.infer_name_load(name),
1528+
&|ty| match ty {
1529+
Type::Dynamic(DynamicType::TodoPEP695ParamSpec) => true,
1530+
Type::NominalInstance(nominal) => {
1531+
nominal.has_known_class(self.db(), KnownClass::ParamSpec)
1532+
}
1533+
_ => false,
1534+
},
1535+
true,
1536+
) {
15321537
return Some(Parameters::todo());
15331538
}
15341539
}

0 commit comments

Comments
 (0)