@@ -1095,6 +1095,74 @@ impl<'db> Type<'db> {
1095
1095
}
1096
1096
}
1097
1097
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
+ }
1098
1166
/// Return true if this type is a [subtype of] type `target`.
1099
1167
///
1100
1168
/// For fully static types, this means that the set of objects represented by `self` is a
@@ -1305,24 +1373,14 @@ impl<'db> Type<'db> {
1305
1373
| Type :: ModuleLiteral ( _) ,
1306
1374
) => false ,
1307
1375
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)
1324
1378
}
1325
1379
1380
+ ( _, Type :: Callable ( _) ) => self
1381
+ . into_callable ( db)
1382
+ . is_some_and ( |callable| callable. has_relation_to ( db, target, relation) ) ,
1383
+
1326
1384
( Type :: ProtocolInstance ( left) , Type :: ProtocolInstance ( right) ) => {
1327
1385
left. has_relation_to ( db, right, relation)
1328
1386
}
@@ -1349,16 +1407,6 @@ impl<'db> Type<'db> {
1349
1407
) => ( self . literal_fallback_instance ( db) )
1350
1408
. is_some_and ( |instance| instance. has_relation_to ( db, target, relation) ) ,
1351
1409
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
-
1362
1410
// A `FunctionLiteral` type is a single-valued type like the other literals handled above,
1363
1411
// so it also, for now, just delegates to its instance fallback.
1364
1412
( Type :: FunctionLiteral ( _) , _) => KnownClass :: FunctionType
@@ -1376,10 +1424,6 @@ impl<'db> Type<'db> {
1376
1424
. to_instance ( db)
1377
1425
. has_relation_to ( db, target, relation) ,
1378
1426
1379
- ( Type :: Callable ( self_callable) , Type :: Callable ( other_callable) ) => {
1380
- self_callable. has_relation_to ( db, other_callable, relation)
1381
- }
1382
-
1383
1427
( Type :: DataclassDecorator ( _) | Type :: DataclassTransformer ( _) , _) => {
1384
1428
// TODO: Implement subtyping using an equivalent `Callable` type.
1385
1429
false
@@ -1456,26 +1500,6 @@ impl<'db> Type<'db> {
1456
1500
self_subclass_ty. has_relation_to ( db, target_subclass_ty, relation)
1457
1501
}
1458
1502
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
-
1479
1503
// `Literal[str]` is a subtype of `type` because the `str` class object is an instance of its metaclass `type`.
1480
1504
// `Literal[abc.ABC]` is a subtype of `abc.ABCMeta` because the `abc.ABC` class object
1481
1505
// is an instance of its metaclass `abc.ABCMeta`.
0 commit comments