diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 2c6de29635..e5256ec9c3 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -8938,6 +8938,23 @@ fn walk_bound_method_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>( visitor.visit_type(db, method.self_instance(db)); } +#[allow(clippy::trivially_copy_pass_by_ref)] +fn into_callable_type_cycle_recover<'db>( + _db: &'db dyn Db, + _value: &CallableType<'db>, + _count: u32, + _self: BoundMethodType<'db>, +) -> salsa::CycleRecoveryAction> { + salsa::CycleRecoveryAction::Iterate +} + +fn into_callable_type_cycle_initial<'db>( + db: &'db dyn Db, + _self: BoundMethodType<'db>, +) -> CallableType<'db> { + CallableType::bottom(db) +} + #[salsa::tracked] impl<'db> BoundMethodType<'db> { /// Returns the type that replaces any `typing.Self` annotations in the bound method signature. @@ -8951,7 +8968,7 @@ impl<'db> BoundMethodType<'db> { self_instance } - #[salsa::tracked(heap_size=ruff_memory_usage::heap_size)] + #[salsa::tracked(cycle_fn=into_callable_type_cycle_recover, cycle_initial=into_callable_type_cycle_initial, heap_size=ruff_memory_usage::heap_size)] pub(crate) fn into_callable_type(self, db: &'db dyn Db) -> CallableType<'db> { let function = self.function(db); let self_instance = self.typing_self_type(db); @@ -9089,9 +9106,8 @@ impl<'db> CallableType<'db> { /// /// Specifically, this represents a callable type with a single signature: /// `(*args: object, **kwargs: object) -> Never`. - #[cfg(test)] - pub(crate) fn bottom(db: &'db dyn Db) -> Type<'db> { - Self::single(db, Signature::bottom()) + pub(crate) fn bottom(db: &'db dyn Db) -> CallableType<'db> { + Self::new(db, CallableSignature::bottom(), false) } /// Return a "normalized" version of this `Callable` type. diff --git a/crates/ty_python_semantic/src/types/property_tests.rs b/crates/ty_python_semantic/src/types/property_tests.rs index 07db77e628..3953b2ef9e 100644 --- a/crates/ty_python_semantic/src/types/property_tests.rs +++ b/crates/ty_python_semantic/src/types/property_tests.rs @@ -158,7 +158,7 @@ mod stable { type_property_test!( bottom_callable_is_subtype_of_all_callable, db, forall types t. t.is_callable_type() - => CallableType::bottom(db).is_subtype_of(db, t) + => Type::Callable(CallableType::bottom(db)).is_subtype_of(db, t) ); // `T` can be assigned to itself. diff --git a/crates/ty_python_semantic/src/types/signatures.rs b/crates/ty_python_semantic/src/types/signatures.rs index 115b6b46de..f25681fdba 100644 --- a/crates/ty_python_semantic/src/types/signatures.rs +++ b/crates/ty_python_semantic/src/types/signatures.rs @@ -43,6 +43,10 @@ impl<'db> CallableSignature<'db> { } } + pub(crate) fn bottom() -> Self { + Self::single(Signature::bottom()) + } + /// Creates a new `CallableSignature` from an iterator of [`Signature`]s. Returns a /// non-callable signature if the iterator is empty. pub(crate) fn from_overloads(overloads: I) -> Self