From 832c9d646f98c0444f242420ae44fa09b772a757 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 20 Jan 2025 19:01:59 +0000 Subject: [PATCH] [red-knot] Simplify and generalize `Type::is_subtype_of` a little bit --- crates/red_knot_python_semantic/src/types.rs | 31 +++++++------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index cafc60b561717..6a54193fe32b0 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -964,12 +964,10 @@ impl<'db> Type<'db> { // `Literal[str]` is a subtype of `type` because the `str` class object is an instance of its metaclass `type`. // `Literal[abc.ABC]` is a subtype of `abc.ABCMeta` because the `abc.ABC` class object // is an instance of its metaclass `abc.ABCMeta`. - ( - Type::ClassLiteral(ClassLiteralType { class: self_class }), - Type::Instance(InstanceType { - class: target_class, - }), - ) => self_class.is_instance_of(db, target_class), + (Type::ClassLiteral(ClassLiteralType { class }), _) => class + .metaclass(db) + .to_instance(db) + .is_subtype_of(db, target), // `type[str]` (== `SubclassOf("str")` in red-knot) describes all possible runtime subclasses // of the class object `str`. It is a subtype of `type` (== `Instance("type")`) because `str` @@ -977,20 +975,13 @@ impl<'db> Type<'db> { // // Similarly `type[enum.Enum]` is a subtype of `enum.EnumMeta` because `enum.Enum` // is an instance of `enum.EnumMeta`. - ( - Type::SubclassOf(subclass_of_ty), - Type::Instance(InstanceType { - class: target_class, - }), - ) => subclass_of_ty - .subclass_of() - .into_class() - .is_some_and(|subclass_class| subclass_class.is_instance_of(db, target_class)), - - // Other than the cases enumerated above, `type[]` and class-literal types just delegate to `Instance("type")` - (Type::SubclassOf(_) | Type::ClassLiteral(_), _) => { - KnownClass::Type.to_instance(db).is_subtype_of(db, target) - } + (Type::SubclassOf(subclass_of_ty), _) => match subclass_of_ty.subclass_of() { + ClassBase::Class(class) => class + .metaclass(db) + .to_instance(db) + .is_subtype_of(db, target), + ClassBase::Dynamic(_) => KnownClass::Type.to_instance(db).is_subtype_of(db, target), + }, // For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::Instance(_SpecialForm)`, // because `Type::KnownInstance(KnownInstanceType::Type)` is a set with exactly one runtime value in it