@@ -1095,6 +1095,74 @@ impl<'db> Type<'db> {
10951095 }
10961096 }
10971097
1098+ pub ( crate ) fn into_callable ( self , db : & ' db dyn Db ) -> Option < Type < ' db > > {
1099+ match self {
1100+ Type :: Callable ( _) => Some ( self ) ,
1101+
1102+ Type :: Dynamic ( _) => Some ( CallableType :: single ( db, Signature :: dynamic ( self ) ) ) ,
1103+
1104+ Type :: FunctionLiteral ( function_literal) => {
1105+ Some ( function_literal. into_callable_type ( db) )
1106+ }
1107+ Type :: BoundMethod ( bound_method) => Some ( bound_method. into_callable_type ( db) ) ,
1108+
1109+ Type :: NominalInstance ( _) | Type :: ProtocolInstance ( _) => {
1110+ let call_symbol = self
1111+ . member_lookup_with_policy (
1112+ db,
1113+ Name :: new_static ( "__call__" ) ,
1114+ MemberLookupPolicy :: NO_INSTANCE_FALLBACK ,
1115+ )
1116+ . place ;
1117+
1118+ if let Place :: Type ( ty, Boundness :: Bound ) = call_symbol {
1119+ ty. into_callable ( db)
1120+ } else {
1121+ None
1122+ }
1123+ }
1124+ Type :: ClassLiteral ( class_literal) => {
1125+ Some ( ClassType :: NonGeneric ( class_literal) . into_callable ( db) )
1126+ }
1127+
1128+ Type :: GenericAlias ( alias) => Some ( ClassType :: Generic ( alias) . into_callable ( db) ) ,
1129+
1130+ // TODO: This is unsound so in future we can consider an opt-in option to disable it.
1131+ Type :: SubclassOf ( subclass_of_ty) => match subclass_of_ty. subclass_of ( ) {
1132+ SubclassOfInner :: Class ( class) => Some ( class. into_callable ( db) ) ,
1133+ SubclassOfInner :: Dynamic ( dynamic) => Some ( CallableType :: single (
1134+ db,
1135+ Signature :: new ( Parameters :: unknown ( ) , Some ( Type :: Dynamic ( dynamic) ) ) ,
1136+ ) ) ,
1137+ } ,
1138+
1139+ Type :: Union ( union) => union. try_map ( db, |element| element. into_callable ( db) ) ,
1140+
1141+ Type :: Never
1142+ | Type :: DataclassTransformer ( _)
1143+ | Type :: AlwaysTruthy
1144+ | Type :: AlwaysFalsy
1145+ | Type :: IntLiteral ( _)
1146+ | Type :: BooleanLiteral ( _)
1147+ | Type :: StringLiteral ( _)
1148+ | Type :: LiteralString
1149+ | Type :: BytesLiteral ( _)
1150+ | Type :: Tuple ( _)
1151+ | Type :: TypeIs ( _) => None ,
1152+
1153+ // TODO
1154+ Type :: MethodWrapper ( _)
1155+ | Type :: WrapperDescriptor ( _)
1156+ | Type :: DataclassDecorator ( _)
1157+ | Type :: ModuleLiteral ( _)
1158+ | Type :: SpecialForm ( _)
1159+ | Type :: KnownInstance ( _)
1160+ | Type :: PropertyInstance ( _)
1161+ | Type :: Intersection ( _)
1162+ | Type :: TypeVar ( _)
1163+ | Type :: BoundSuper ( _) => None ,
1164+ }
1165+ }
10981166 /// Return true if this type is a [subtype of] type `target`.
10991167 ///
11001168 /// For fully static types, this means that the set of objects represented by `self` is a
@@ -1305,24 +1373,14 @@ impl<'db> Type<'db> {
13051373 | Type :: ModuleLiteral ( _) ,
13061374 ) => false ,
13071375
1308- ( Type :: NominalInstance ( _) | Type :: ProtocolInstance ( _) , Type :: Callable ( _) ) => {
1309- let call_symbol = self
1310- . member_lookup_with_policy (
1311- db,
1312- Name :: new_static ( "__call__" ) ,
1313- MemberLookupPolicy :: NO_INSTANCE_FALLBACK ,
1314- )
1315- . place ;
1316- // If the type of __call__ is a subtype of a callable type, this instance is.
1317- // Don't add other special cases here; our subtyping of a callable type
1318- // shouldn't get out of sync with the calls we will actually allow.
1319- if let Place :: Type ( t, Boundness :: Bound ) = call_symbol {
1320- t. has_relation_to ( db, target, relation)
1321- } else {
1322- false
1323- }
1376+ ( Type :: Callable ( self_callable) , Type :: Callable ( other_callable) ) => {
1377+ self_callable. has_relation_to ( db, other_callable, relation)
13241378 }
13251379
1380+ ( _, Type :: Callable ( _) ) => self
1381+ . into_callable ( db)
1382+ . is_some_and ( |callable| callable. has_relation_to ( db, target, relation) ) ,
1383+
13261384 ( Type :: ProtocolInstance ( left) , Type :: ProtocolInstance ( right) ) => {
13271385 left. has_relation_to ( db, right, relation)
13281386 }
@@ -1349,16 +1407,6 @@ impl<'db> Type<'db> {
13491407 ) => ( self . literal_fallback_instance ( db) )
13501408 . is_some_and ( |instance| instance. has_relation_to ( db, target, relation) ) ,
13511409
1352- ( Type :: FunctionLiteral ( self_function_literal) , Type :: Callable ( _) ) => {
1353- self_function_literal
1354- . into_callable_type ( db)
1355- . has_relation_to ( db, target, relation)
1356- }
1357-
1358- ( Type :: BoundMethod ( self_bound_method) , Type :: Callable ( _) ) => self_bound_method
1359- . into_callable_type ( db)
1360- . has_relation_to ( db, target, relation) ,
1361-
13621410 // A `FunctionLiteral` type is a single-valued type like the other literals handled above,
13631411 // so it also, for now, just delegates to its instance fallback.
13641412 ( Type :: FunctionLiteral ( _) , _) => KnownClass :: FunctionType
@@ -1376,10 +1424,6 @@ impl<'db> Type<'db> {
13761424 . to_instance ( db)
13771425 . has_relation_to ( db, target, relation) ,
13781426
1379- ( Type :: Callable ( self_callable) , Type :: Callable ( other_callable) ) => {
1380- self_callable. has_relation_to ( db, other_callable, relation)
1381- }
1382-
13831427 ( Type :: DataclassDecorator ( _) | Type :: DataclassTransformer ( _) , _) => {
13841428 // TODO: Implement subtyping using an equivalent `Callable` type.
13851429 false
@@ -1456,26 +1500,6 @@ impl<'db> Type<'db> {
14561500 self_subclass_ty. has_relation_to ( db, target_subclass_ty, relation)
14571501 }
14581502
1459- ( Type :: ClassLiteral ( class_literal) , Type :: Callable ( _) ) => {
1460- ClassType :: NonGeneric ( class_literal)
1461- . into_callable ( db)
1462- . has_relation_to ( db, target, relation)
1463- }
1464-
1465- ( Type :: GenericAlias ( alias) , Type :: Callable ( _) ) => ClassType :: Generic ( alias)
1466- . into_callable ( db)
1467- . has_relation_to ( db, target, relation) ,
1468-
1469- // TODO: This is unsound so in future we can consider an opt-in option to disable it.
1470- ( Type :: SubclassOf ( subclass_of_ty) , Type :: Callable ( _) )
1471- if subclass_of_ty. subclass_of ( ) . into_class ( ) . is_some ( ) =>
1472- {
1473- let class = subclass_of_ty. subclass_of ( ) . into_class ( ) . unwrap ( ) ;
1474- class
1475- . into_callable ( db)
1476- . has_relation_to ( db, target, relation)
1477- }
1478-
14791503 // `Literal[str]` is a subtype of `type` because the `str` class object is an instance of its metaclass `type`.
14801504 // `Literal[abc.ABC]` is a subtype of `abc.ABCMeta` because the `abc.ABC` class object
14811505 // is an instance of its metaclass `abc.ABCMeta`.
0 commit comments