mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 21:35:58 +00:00
[red-knot] Improve Type::is_disjoint_from()
for KnownInstanceType
s (#15261)
This commit is contained in:
parent
980ce941c7
commit
0743838438
1 changed files with 25 additions and 7 deletions
|
@ -1194,19 +1194,22 @@ impl<'db> Type<'db> {
|
||||||
ty.bool(db).is_always_true()
|
ty.bool(db).is_always_true()
|
||||||
}
|
}
|
||||||
|
|
||||||
(Type::SubclassOf(_), _) | (_, Type::SubclassOf(_)) => {
|
(Type::SubclassOf(_), other) | (other, Type::SubclassOf(_)) => {
|
||||||
// TODO: Once we have support for final classes, we can determine disjointness in some cases
|
// TODO: Once we have support for final classes, we can determine disjointness in more cases
|
||||||
// here. However, note that it might be better to turn `Type::SubclassOf('FinalClass')` into
|
// here. However, note that it might be better to turn `Type::SubclassOf('FinalClass')` into
|
||||||
// `Type::ClassLiteral('FinalClass')` during construction, instead of adding special cases for
|
// `Type::ClassLiteral('FinalClass')` during construction, instead of adding special cases for
|
||||||
// final classes inside `Type::SubclassOf` everywhere.
|
// final classes inside `Type::SubclassOf` everywhere.
|
||||||
false
|
other.is_disjoint_from(db, KnownClass::Type.to_instance(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
(Type::KnownInstance(left), right) => {
|
(Type::KnownInstance(known_instance), Type::Instance(InstanceType { class }))
|
||||||
left.instance_fallback(db).is_disjoint_from(db, right)
|
| (Type::Instance(InstanceType { class }), Type::KnownInstance(known_instance)) => {
|
||||||
|
!known_instance.is_instance_of(db, class)
|
||||||
}
|
}
|
||||||
(left, Type::KnownInstance(right)) => {
|
|
||||||
left.is_disjoint_from(db, right.instance_fallback(db))
|
(known_instance_ty @ Type::KnownInstance(_), Type::Tuple(_))
|
||||||
|
| (Type::Tuple(_), known_instance_ty @ Type::KnownInstance(_)) => {
|
||||||
|
known_instance_ty.is_disjoint_from(db, KnownClass::Tuple.to_instance(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2352,6 +2355,15 @@ impl<'db> KnownClass {
|
||||||
.unwrap_or(Type::subclass_of_base(ClassBase::Unknown))
|
.unwrap_or(Type::subclass_of_base(ClassBase::Unknown))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if this symbol can be resolved to a class definition `class` in typeshed,
|
||||||
|
/// *and* `class` is a subclass of `other`.
|
||||||
|
pub fn is_subclass_of(self, db: &'db dyn Db, other: Class<'db>) -> bool {
|
||||||
|
known_module_symbol(db, self.canonical_module(db), self.as_str())
|
||||||
|
.ignore_possibly_unbound()
|
||||||
|
.and_then(Type::into_class_literal)
|
||||||
|
.is_some_and(|ClassLiteralType { class }| class.is_subclass_of(db, other))
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the module in which we should look up the definition for this class
|
/// Return the module in which we should look up the definition for this class
|
||||||
pub(crate) fn canonical_module(self, db: &'db dyn Db) -> KnownModule {
|
pub(crate) fn canonical_module(self, db: &'db dyn Db) -> KnownModule {
|
||||||
match self {
|
match self {
|
||||||
|
@ -2738,6 +2750,10 @@ impl<'db> KnownInstanceType<'db> {
|
||||||
self.class().to_instance(db)
|
self.class().to_instance(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_instance_of(self, db: &'db dyn Db, class: Class<'db>) -> bool {
|
||||||
|
self.class().is_subclass_of(db, class)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn try_from_file_and_name(db: &'db dyn Db, file: File, symbol_name: &str) -> Option<Self> {
|
pub fn try_from_file_and_name(db: &'db dyn Db, file: File, symbol_name: &str) -> Option<Self> {
|
||||||
let candidate = match symbol_name {
|
let candidate = match symbol_name {
|
||||||
"Any" => Self::Any,
|
"Any" => Self::Any,
|
||||||
|
@ -4160,6 +4176,8 @@ pub(crate) mod tests {
|
||||||
#[test_case(Ty::SubclassOfBuiltinClass("object"), Ty::None)]
|
#[test_case(Ty::SubclassOfBuiltinClass("object"), Ty::None)]
|
||||||
#[test_case(Ty::SubclassOfBuiltinClass("str"), Ty::LiteralString)]
|
#[test_case(Ty::SubclassOfBuiltinClass("str"), Ty::LiteralString)]
|
||||||
#[test_case(Ty::AlwaysFalsy, Ty::AlwaysTruthy)]
|
#[test_case(Ty::AlwaysFalsy, Ty::AlwaysTruthy)]
|
||||||
|
#[test_case(Ty::Tuple(vec![]), Ty::TypingLiteral)]
|
||||||
|
#[test_case(Ty::TypingLiteral, Ty::SubclassOfBuiltinClass("object"))]
|
||||||
fn is_disjoint_from(a: Ty, b: Ty) {
|
fn is_disjoint_from(a: Ty, b: Ty) {
|
||||||
let db = setup_db();
|
let db = setup_db();
|
||||||
let a = a.into_type(&db);
|
let a = a.into_type(&db);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue