mirror of https://github.com/astral-sh/ruff
[red-knot] Add new property tests for subtyping with "bottom" callable (#17635)
## Summary
I remember we discussed about adding this as a property tests so here I
am.
## Test Plan
```console
❯ QUICKCHECK_TESTS=10000000 cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable
Finished `release` profile [optimized] target(s) in 0.10s
Running unittests src/lib.rs (target/release/deps/red_knot_python_semantic-e41596ca2dbd0e98)
running 1 test
test types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 233 filtered out; finished in 30.91s
```
This commit is contained in:
parent
6ab32a7746
commit
0251679f87
|
|
@ -537,6 +537,11 @@ impl<'db> Type<'db> {
|
||||||
matches!(self, Type::Never)
|
matches!(self, Type::Never)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is [`Type::Callable`].
|
||||||
|
pub const fn is_callable_type(&self) -> bool {
|
||||||
|
matches!(self, Type::Callable(..))
|
||||||
|
}
|
||||||
|
|
||||||
fn is_none(&self, db: &'db dyn Db) -> bool {
|
fn is_none(&self, db: &'db dyn Db) -> bool {
|
||||||
self.into_instance()
|
self.into_instance()
|
||||||
.is_some_and(|instance| instance.class().is_known(db, KnownClass::NoneType))
|
.is_some_and(|instance| instance.class().is_known(db, KnownClass::NoneType))
|
||||||
|
|
@ -6571,6 +6576,18 @@ impl<'db> CallableType<'db> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a callable type which represents a fully-static "bottom" callable.
|
||||||
|
///
|
||||||
|
/// 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> {
|
||||||
|
Type::Callable(CallableType::single(
|
||||||
|
db,
|
||||||
|
Signature::new(Parameters::object(db), Some(Type::Never)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// Return a "normalized" version of this `Callable` type.
|
/// Return a "normalized" version of this `Callable` type.
|
||||||
///
|
///
|
||||||
/// See [`Type::normalized`] for more details.
|
/// See [`Type::normalized`] for more details.
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ macro_rules! type_property_test {
|
||||||
|
|
||||||
mod stable {
|
mod stable {
|
||||||
use super::union;
|
use super::union;
|
||||||
use crate::types::Type;
|
use crate::types::{CallableType, Type};
|
||||||
|
|
||||||
// Reflexivity: `T` is equivalent to itself.
|
// Reflexivity: `T` is equivalent to itself.
|
||||||
type_property_test!(
|
type_property_test!(
|
||||||
|
|
@ -169,6 +169,14 @@ mod stable {
|
||||||
forall types t. t.is_fully_static(db) => Type::Never.is_subtype_of(db, t)
|
forall types t. t.is_fully_static(db) => Type::Never.is_subtype_of(db, t)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Similar to `Never`, a fully-static "bottom" callable type should be a subtype of all
|
||||||
|
// fully-static callable types
|
||||||
|
type_property_test!(
|
||||||
|
bottom_callable_is_subtype_of_all_fully_static_callable, db,
|
||||||
|
forall types t. t.is_callable_type() && t.is_fully_static(db)
|
||||||
|
=> CallableType::bottom(db).is_subtype_of(db, t)
|
||||||
|
);
|
||||||
|
|
||||||
// For any two fully static types, each type in the pair must be a subtype of their union.
|
// For any two fully static types, each type in the pair must be a subtype of their union.
|
||||||
type_property_test!(
|
type_property_test!(
|
||||||
all_fully_static_type_pairs_are_subtype_of_their_union, db,
|
all_fully_static_type_pairs_are_subtype_of_their_union, db,
|
||||||
|
|
|
||||||
|
|
@ -934,6 +934,19 @@ impl<'db> Parameters<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return parameters that represents `(*args: object, **kwargs: object)`.
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) fn object(db: &'db dyn Db) -> Self {
|
||||||
|
Self {
|
||||||
|
value: vec![
|
||||||
|
Parameter::variadic(Name::new_static("args")).with_annotated_type(Type::object(db)),
|
||||||
|
Parameter::keyword_variadic(Name::new_static("kwargs"))
|
||||||
|
.with_annotated_type(Type::object(db)),
|
||||||
|
],
|
||||||
|
is_gradual: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn from_parameters(
|
fn from_parameters(
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
definition: Definition<'db>,
|
definition: Definition<'db>,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue