@@ -769,34 +769,10 @@ impl<'db> Type<'db> {
769769 Type :: subclass_of ( class) . is_subtype_of ( db, target)
770770 }
771771
772- // As the `unreachable!()` message says, non-fully-static `SubclassOf` types such as
773- // `type[Any]`,` type[Unknown]` and `type[Todo]` should all be handled right at the top of this function.
774- (
775- Type :: SubclassOf ( SubclassOfType {
776- base : ClassBase :: Any | ClassBase :: Unknown | ClassBase :: Todo ( _) ,
777- } ) ,
778- _,
779- )
780- | (
781- _,
782- Type :: SubclassOf ( SubclassOfType {
783- base : ClassBase :: Any | ClassBase :: Unknown | ClassBase :: Todo ( _) ,
784- } ) ,
785- ) => unreachable ! (
786- "Non-fully-static types should be handled at the top of this function!"
787- ) ,
788-
789- // For example, `type[bool]` describes all possible runtime subclasses of the class `bool`,
790- // and `type[int]` describes all possible runtime subclasses of the class `int`.
791- // The first set is a subset of the second set, because `bool` is itself a subclass of `int`.
792- (
793- Type :: SubclassOf ( SubclassOfType {
794- base : ClassBase :: Class ( self_class) ,
795- } ) ,
796- Type :: SubclassOf ( SubclassOfType {
797- base : ClassBase :: Class ( target_class) ,
798- } ) ,
799- ) => self_class. is_subclass_of ( db, target_class) ,
772+ // This branch asks: given two types `type[T]` and `type[S]`, is `type[T]` a subtype of `type[S]`?
773+ ( Type :: SubclassOf ( self_subclass_ty) , Type :: SubclassOf ( target_subclass_ty) ) => {
774+ self_subclass_ty. is_subtype_of ( db, target_subclass_ty)
775+ }
800776
801777 // `type[str]` (== `SubclassOf("str")` in red-knot) describes all possible runtime subclasses
802778 // of the class object `str`. It is a subtype of `type` (== `Instance("type")`) because `str`
@@ -1046,9 +1022,8 @@ impl<'db> Type<'db> {
10461022 | Type :: SliceLiteral ( ..)
10471023 | Type :: StringLiteral ( ..)
10481024 | Type :: LiteralString ,
1049- ) => true ,
1050-
1051- (
1025+ )
1026+ | (
10521027 Type :: ClassLiteral ( ..)
10531028 | Type :: ModuleLiteral ( ..)
10541029 | Type :: BooleanLiteral ( ..)
@@ -3128,6 +3103,22 @@ impl<'db> SubclassOfType<'db> {
31283103 fn member ( self , db : & ' db dyn Db , name : & str ) -> Symbol < ' db > {
31293104 Type :: from ( self . base ) . member ( db, name)
31303105 }
3106+
3107+ fn is_subtype_of ( self , db : & ' db dyn Db , other : SubclassOfType < ' db > ) -> bool {
3108+ match ( self . base , other. base ) {
3109+ // Non-fully-static types do not participate in subtyping
3110+ ( ClassBase :: Any | ClassBase :: Unknown | ClassBase :: Todo ( _) , _)
3111+ | ( _, ClassBase :: Any | ClassBase :: Unknown | ClassBase :: Todo ( _) ) => false ,
3112+
3113+ // For example, `type[bool]` describes all possible runtime subclasses of the class `bool`,
3114+ // and `type[int]` describes all possible runtime subclasses of the class `int`.
3115+ // The first set is a subset of the second set, because `bool` is itself a subclass of `int`.
3116+ ( ClassBase :: Class ( self_class) , ClassBase :: Class ( other_class) ) => {
3117+ // N.B. The subclass relation is fully static
3118+ self_class. is_subclass_of ( db, other_class)
3119+ }
3120+ }
3121+ }
31313122}
31323123
31333124/// A type representing the set of runtime objects which are instances of a certain class.
@@ -3138,6 +3129,7 @@ pub struct InstanceType<'db> {
31383129
31393130impl < ' db > InstanceType < ' db > {
31403131 fn is_subtype_of ( self , db : & ' db dyn Db , other : InstanceType < ' db > ) -> bool {
3132+ // N.B. The subclass relation is fully static
31413133 self . class . is_subclass_of ( db, other. class )
31423134 }
31433135}
0 commit comments