@@ -605,104 +605,50 @@ impl<'db> Type<'db> {
605605 ///
606606 /// [subtype of]: https://typing.readthedocs.io/en/latest/spec/concepts.html#subtype-supertype-and-type-equivalence
607607 pub ( crate ) fn is_subtype_of ( self , db : & ' db dyn Db , target : Type < ' db > ) -> bool {
608+ // Two equivalent types are always equal to each other.
609+ //
610+ // "Equivalent to" here means that the two types are both fully static
611+ // and can be determined to point to exactly the same set of possible runtime objects.
612+ // For example, `int` is a subtype of `int` because `int` and `int` are equivalent to each other.
613+ // Equally, `type[object]` is a subtype of `type`,
614+ // because the former type expresses "all subclasses of `object`"
615+ // while the latter expresses "all instances of `type`",
616+ // and these are exactly the same set of objects at runtime.
608617 if self . is_equivalent_to ( db, target) {
609618 return true ;
610619 }
620+
621+ // Non-fully-static types do not participate in subtyping.
622+ //
623+ // Type `A` can only be a subtype of type `B` if the set of possible runtime objects
624+ // that `A` represents is a subset of the set of possible runtime objects that `B` represents.
625+ // But the set of objects that a fully static type represents is (either partially or wholly) unknown,
626+ // so the question is simply unanswerable for fully static types.
611627 if !self . is_fully_static ( db) || !target. is_fully_static ( db) {
612628 return false ;
613629 }
630+
614631 match ( self , target) {
632+ // We should have handled these immediately above.
633+ ( Type :: Any | Type :: Unknown | Type :: Todo ( _) , _)
634+ | ( _, Type :: Any | Type :: Unknown | Type :: Todo ( _) ) => {
635+ unreachable ! ( "Non-fully-static types do not participate in subtyping!" )
636+ }
637+
638+ // `Never` is the bottom type, the empty set.
639+ // It is a subtype of all other fully static types.
640+ // No other fully static type is a subtype of `Never`.
615641 ( Type :: Never , _) => true ,
616642 ( _, Type :: Never ) => false ,
617- ( _, Type :: Instance ( InstanceType { class } ) )
618- if class. is_known ( db, KnownClass :: Object ) =>
619- {
620- true
621- }
622- ( Type :: Instance ( InstanceType { class } ) , _)
623- if class. is_known ( db, KnownClass :: Object ) =>
624- {
625- false
626- }
627- ( Type :: BooleanLiteral ( _) , Type :: Instance ( InstanceType { class } ) )
628- if matches ! ( class. known( db) , Some ( KnownClass :: Bool | KnownClass :: Int ) ) =>
629- {
630- true
631- }
632- ( Type :: IntLiteral ( _) , Type :: Instance ( InstanceType { class } ) )
633- if class. is_known ( db, KnownClass :: Int ) =>
634- {
635- true
636- }
637- ( Type :: StringLiteral ( _) , Type :: LiteralString ) => true ,
638- (
639- Type :: StringLiteral ( _) | Type :: LiteralString ,
640- Type :: Instance ( InstanceType { class } ) ,
641- ) if class. is_known ( db, KnownClass :: Str ) => true ,
642- ( Type :: BytesLiteral ( _) , Type :: Instance ( InstanceType { class } ) )
643- if class. is_known ( db, KnownClass :: Bytes ) =>
644- {
645- true
646- }
647- ( Type :: Tuple ( self_tuple) , Type :: Tuple ( target_tuple) ) => {
648- let self_elements = self_tuple. elements ( db) ;
649- let target_elements = target_tuple. elements ( db) ;
650- self_elements. len ( ) == target_elements. len ( )
651- && self_elements. iter ( ) . zip ( target_elements) . all (
652- |( self_element, target_element) | {
653- self_element. is_subtype_of ( db, * target_element)
654- } ,
655- )
656- }
657- (
658- Type :: ClassLiteral ( ClassLiteralType { class : self_class } ) ,
659- Type :: SubclassOf ( SubclassOfType {
660- base : ClassBase :: Class ( target_class) ,
661- } ) ,
662- ) => self_class. is_subclass_of ( db, target_class) ,
663- (
664- Type :: Instance ( _) ,
665- Type :: SubclassOf ( SubclassOfType {
666- base : ClassBase :: Class ( target_class) ,
667- } ) ,
668- ) if target_class. is_known ( db, KnownClass :: Object ) => {
669- self . is_subtype_of ( db, KnownClass :: Type . to_instance ( db) )
670- }
671- (
672- Type :: SubclassOf ( SubclassOfType {
673- base : ClassBase :: Class ( self_class) ,
674- } ) ,
675- Type :: SubclassOf ( SubclassOfType {
676- base : ClassBase :: Class ( target_class) ,
677- } ) ,
678- ) => self_class. is_subclass_of ( db, target_class) ,
679- // C ⊆ type
680- // type[C] ⊆ type
681- // Though note that this works regardless of which metaclass C has, not just for type.
682- (
683- Type :: ClassLiteral ( ClassLiteralType { class : self_class } )
684- | Type :: SubclassOf ( SubclassOfType {
685- base : ClassBase :: Class ( self_class) ,
686- } ) ,
687- Type :: Instance ( InstanceType {
688- class : target_class,
689- } ) ,
690- ) if self_class
691- . metaclass ( db)
692- . into_class_literal ( )
693- . map ( |meta| meta. class . is_subclass_of ( db, target_class) )
694- . unwrap_or ( false ) =>
695- {
696- true
697- }
698- ( Type :: Union ( union) , ty) => union
643+
644+ ( Type :: Union ( union) , _) => union
699645 . elements ( db)
700646 . iter ( )
701- . all ( |& elem_ty| elem_ty. is_subtype_of ( db, ty ) ) ,
702- ( ty , Type :: Union ( union) ) => union
647+ . all ( |& elem_ty| elem_ty. is_subtype_of ( db, target ) ) ,
648+ ( _ , Type :: Union ( union) ) => union
703649 . elements ( db)
704650 . iter ( )
705- . any ( |& elem_ty| ty . is_subtype_of ( db, elem_ty) ) ,
651+ . any ( |& elem_ty| self . is_subtype_of ( db, elem_ty) ) ,
706652 ( Type :: Intersection ( self_intersection) , Type :: Intersection ( target_intersection) ) => {
707653 // Check that all target positive values are covered in self positive values
708654 target_intersection
@@ -729,26 +675,151 @@ impl<'db> Type<'db> {
729675 } )
730676 } )
731677 }
732- ( Type :: Intersection ( intersection) , ty ) => intersection
678+ ( Type :: Intersection ( intersection) , _ ) => intersection
733679 . positive ( db)
734680 . iter ( )
735- . any ( |& elem_ty| elem_ty. is_subtype_of ( db, ty ) ) ,
736- ( ty , Type :: Intersection ( intersection) ) => {
681+ . any ( |& elem_ty| elem_ty. is_subtype_of ( db, target ) ) ,
682+ ( _ , Type :: Intersection ( intersection) ) => {
737683 intersection
738684 . positive ( db)
739685 . iter ( )
740- . all ( |& pos_ty| ty . is_subtype_of ( db, pos_ty) )
686+ . all ( |& pos_ty| self . is_subtype_of ( db, pos_ty) )
741687 && intersection
742688 . negative ( db)
743689 . iter ( )
744- . all ( |& neg_ty| neg_ty. is_disjoint_from ( db, ty ) )
690+ . all ( |& neg_ty| neg_ty. is_disjoint_from ( db, self ) )
745691 }
692+
693+ // All `StringLiteral` types are a subtype of `LiteralString`.
694+ ( Type :: StringLiteral ( _) , Type :: LiteralString ) => true ,
695+
696+ // Except for the special `LiteralString` case above,
697+ // most `Literal` types delegate to their instance fallbacks
698+ // unless `self` is exactly equivalent to `target` (handled above)
699+ ( Type :: StringLiteral ( _) | Type :: LiteralString , _) => {
700+ KnownClass :: Str . to_instance ( db) . is_subtype_of ( db, target)
701+ }
702+ ( Type :: BooleanLiteral ( _) , _) => {
703+ KnownClass :: Bool . to_instance ( db) . is_subtype_of ( db, target)
704+ }
705+ ( Type :: IntLiteral ( _) , _) => KnownClass :: Int . to_instance ( db) . is_subtype_of ( db, target) ,
706+ ( Type :: BytesLiteral ( _) , _) => {
707+ KnownClass :: Bytes . to_instance ( db) . is_subtype_of ( db, target)
708+ }
709+ ( Type :: ModuleLiteral ( _) , _) => KnownClass :: ModuleType
710+ . to_instance ( db)
711+ . is_subtype_of ( db, target) ,
712+ ( Type :: SliceLiteral ( _) , _) => {
713+ KnownClass :: Slice . to_instance ( db) . is_subtype_of ( db, target)
714+ }
715+
716+ // A `FunctionLiteral` type is a single-valued type like the other literals handled above,
717+ // so it also, for now, just delegates to its instance fallback.
718+ // This will change in a way similar to the `LiteralString`/`StringLiteral()` case above
719+ // when we add support for `typing.Callable`.
720+ ( Type :: FunctionLiteral ( _) , _) => KnownClass :: FunctionType
721+ . to_instance ( db)
722+ . is_subtype_of ( db, target) ,
723+
724+ // A fully static heterogenous tuple type `A` is a subtype of a fully static heterogeneous tuple type `B`
725+ // iff the two tuple types have the same number of elements and each element-type in `A` is a subtype
726+ // of the element-type at the same index in `B`. (Now say that 5 times fast.)
727+ //
728+ // For example: `tuple[bool, bool]` is a subtype of `tuple[int, int]`,
729+ // but `tuple[bool, bool, bool]` is not a subtype of `tuple[int, int]`
730+ ( Type :: Tuple ( self_tuple) , Type :: Tuple ( target_tuple) ) => {
731+ let self_elements = self_tuple. elements ( db) ;
732+ let target_elements = target_tuple. elements ( db) ;
733+ self_elements. len ( ) == target_elements. len ( )
734+ && self_elements. iter ( ) . zip ( target_elements) . all (
735+ |( self_element, target_element) | {
736+ self_element. is_subtype_of ( db, * target_element)
737+ } ,
738+ )
739+ }
740+
741+ // Other than the special tuple-to-tuple case handled, above,
742+ // tuple subtyping delegates to `Instance(tuple)` in the same way as the literal types.
743+ //
744+ // All heterogenous tuple types are subtypes of `Instance(<tuple>)`:
745+ // `Instance(<some class T>)` expresses "the set of all possible instances of the class `T`";
746+ // consequently, `Instance(<tuple>)` expresses "the set of all possible instances of the class `tuple`".
747+ // This type can be spelled in type annotations as `tuple[object, ...]` (since `tuple` is covariant).
748+ //
749+ // Note that this is not the same type as the type spelled in type annotations as `tuple`;
750+ // as that type is equivalent to `type[Any, ...]` (and therefore not a fully static type).
751+ ( Type :: Tuple ( _) , _) => KnownClass :: Tuple . to_instance ( db) . is_subtype_of ( db, target) ,
752+
753+ // `Type::ClassLiteral(T)` expresses "the set of size one with only the class `T` in it;
754+ // `Type::SubclassOf(S)` expresses "the set that contains all subclasses of the class `S`".
755+ // The first is only a subtype of the second if `T` is a subclass of `S`.
756+ //
757+ // For example, `Literal[int]` and `Literal[bool]` are both subtypes of `type[int]`.
758+ (
759+ Type :: ClassLiteral ( ClassLiteralType { class : self_class } ) ,
760+ Type :: SubclassOf ( SubclassOfType {
761+ base : ClassBase :: Class ( target_class) ,
762+ } ) ,
763+ ) => self_class. is_subclass_of ( db, target_class) ,
764+
765+ // `Literal[str]` is a subtype of `type` because `str` is an instance of `type`.
766+ // `Literal[enum.Enum]` is a subtype of `enum.EnumMeta` because `enum.Enum`
767+ // is an instance of `enum.EnumMeta`.
768+ (
769+ Type :: ClassLiteral ( self_class_ty) ,
770+ Type :: Instance ( InstanceType {
771+ class : target_class,
772+ } ) ,
773+ ) => self_class_ty. is_instance_of ( db, target_class) ,
774+
775+ // Other than the cases enumerated above,
776+ // class literals aren't subtypes of any other types.
777+ ( Type :: ClassLiteral ( _) , _) => false ,
778+
779+ // `type[T]` delegates to `Literal[T]`
780+ // when deciding if `type[T]` is a subtype of another type.
781+ (
782+ Type :: SubclassOf ( SubclassOfType {
783+ base : ClassBase :: Class ( self_class) ,
784+ } ) ,
785+ _,
786+ ) => Type :: class_literal ( self_class) . is_subtype_of ( db, target) ,
787+
788+ // As the `unreachable!()` message says, these should all be handled
789+ // right at the top of this function.
790+ (
791+ Type :: SubclassOf ( SubclassOfType {
792+ base : ClassBase :: Any | ClassBase :: Unknown | ClassBase :: Todo ( _) ,
793+ } ) ,
794+ _,
795+ ) => unreachable ! (
796+ "Non-fully-static types should be handled at the top of this function!"
797+ ) ,
798+
799+ // For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::Instance(_SpecialForm)`,
800+ // because the symbol `typing.Type` is an instance of `typing._SpecialForm` at runtime
746801 ( Type :: KnownInstance ( left) , right) => {
747802 left. instance_fallback ( db) . is_subtype_of ( db, right)
748803 }
804+
805+ // For example, `Instance(ABCMeta)` is a subtype of `type[object]`,
806+ // because (since `ABCMeta` subclasses `type`) all instances of `ABCMeta` are instances of `type`,
807+ // and all instances of `type` are members of the type `type[object]`
808+ (
809+ Type :: Instance ( _) ,
810+ Type :: SubclassOf ( SubclassOfType {
811+ base : ClassBase :: Class ( target_class) ,
812+ } ) ,
813+ ) if target_class. is_known ( db, KnownClass :: Object ) => {
814+ self . is_subtype_of ( db, KnownClass :: Type . to_instance ( db) )
815+ }
816+
817+ // `bool` is a subtype of `int`, because all instances of `bool` are also instances of `int`.
749818 ( Type :: Instance ( left) , Type :: Instance ( right) ) => left. is_instance_of ( db, right. class ) ,
750- // TODO
751- _ => false ,
819+
820+ // Other than the special cases enumerated above,
821+ // `Instance` types are never subtypes of any other variants
822+ ( Type :: Instance ( _) , _) => false ,
752823 }
753824 }
754825
@@ -2965,6 +3036,18 @@ impl<'db> ClassLiteralType<'db> {
29653036 fn member ( self , db : & ' db dyn Db , name : & str ) -> Symbol < ' db > {
29663037 self . class . class_member ( db, name)
29673038 }
3039+
3040+ /// Return `true` if the singleton class object represented by this type
3041+ /// is an instance of the class `other`.
3042+ ///
3043+ /// A class is an instance of its metaclass; consequently,
3044+ /// a class will only ever be an instance of another class
3045+ /// if its metaclass is a subclass of that other class.
3046+ fn is_instance_of ( self , db : & ' db dyn Db , other : Class < ' db > ) -> bool {
3047+ self . class . metaclass ( db) . into_class_literal ( ) . is_some_and (
3048+ |ClassLiteralType { class : metaclass } | metaclass. is_subclass_of ( db, other) ,
3049+ )
3050+ }
29683051}
29693052
29703053impl < ' db > From < ClassLiteralType < ' db > > for Type < ' db > {
@@ -3168,7 +3251,7 @@ pub(crate) mod tests {
31683251 use super :: * ;
31693252 use crate :: db:: tests:: { setup_db, TestDb , TestDbBuilder } ;
31703253 use crate :: stdlib:: typing_symbol;
3171- use crate :: PythonVersion ;
3254+ use crate :: { resolve_module , PythonVersion } ;
31723255 use ruff_db:: files:: system_path_to_file;
31733256 use ruff_db:: parsed:: parsed_module;
31743257 use ruff_db:: system:: DbWithTestSystem ;
@@ -3208,6 +3291,8 @@ pub(crate) mod tests {
32083291 Tuple ( Vec < Ty > ) ,
32093292 SubclassOfAny ,
32103293 SubclassOfBuiltinClass ( & ' static str ) ,
3294+ StdlibModule ( CoreStdlibModule ) ,
3295+ SliceLiteral ( i32 , i32 , i32 ) ,
32113296 }
32123297
32133298 impl Ty {
@@ -3258,6 +3343,15 @@ pub(crate) mod tests {
32583343 . expect_class_literal ( )
32593344 . class ,
32603345 ) ,
3346+ Ty :: StdlibModule ( module) => {
3347+ Type :: ModuleLiteral ( resolve_module ( db, & module. name ( ) ) . unwrap ( ) . file ( ) )
3348+ }
3349+ Ty :: SliceLiteral ( start, stop, step) => Type :: SliceLiteral ( SliceLiteralType :: new (
3350+ db,
3351+ Some ( start) ,
3352+ Some ( stop) ,
3353+ Some ( step) ,
3354+ ) ) ,
32613355 }
32623356 }
32633357 }
@@ -3384,6 +3478,13 @@ pub(crate) mod tests {
33843478 #[ test_case( Ty :: TypingLiteral , Ty :: BuiltinInstance ( "object" ) ) ]
33853479 #[ test_case( Ty :: AbcClassLiteral ( "ABC" ) , Ty :: AbcInstance ( "ABCMeta" ) ) ]
33863480 #[ test_case( Ty :: AbcInstance ( "ABCMeta" ) , Ty :: SubclassOfBuiltinClass ( "object" ) ) ]
3481+ #[ test_case( Ty :: Tuple ( vec![ Ty :: BuiltinInstance ( "int" ) ] ) , Ty :: BuiltinInstance ( "tuple" ) ) ]
3482+ #[ test_case( Ty :: BuiltinClassLiteral ( "str" ) , Ty :: BuiltinInstance ( "type" ) ) ]
3483+ #[ test_case(
3484+ Ty :: StdlibModule ( CoreStdlibModule :: Typing ) ,
3485+ Ty :: KnownClassInstance ( KnownClass :: ModuleType )
3486+ ) ]
3487+ #[ test_case( Ty :: SliceLiteral ( 1 , 2 , 3 ) , Ty :: BuiltinInstance ( "slice" ) ) ]
33873488 fn is_subtype_of ( from : Ty , to : Ty ) {
33883489 let db = setup_db ( ) ;
33893490 assert ! ( from. into_type( & db) . is_subtype_of( & db, to. into_type( & db) ) ) ;
0 commit comments