@@ -12,6 +12,7 @@ pub(crate) use self::display::TypeArrayDisplay;
12
12
pub ( crate ) use self :: infer:: {
13
13
infer_deferred_types, infer_definition_types, infer_expression_types, infer_scope_types,
14
14
} ;
15
+ pub ( crate ) use self :: signatures:: Signature ;
15
16
use crate :: module_resolver:: file_to_module;
16
17
use crate :: semantic_index:: ast_ids:: HasScopedAstId ;
17
18
use crate :: semantic_index:: definition:: Definition ;
@@ -35,6 +36,7 @@ mod display;
35
36
mod infer;
36
37
mod mro;
37
38
mod narrow;
39
+ mod signatures;
38
40
mod unpacker;
39
41
40
42
#[ salsa:: tracked( return_ref) ]
@@ -1271,11 +1273,11 @@ impl<'db> Type<'db> {
1271
1273
Type :: FunctionLiteral ( function_type) => {
1272
1274
if function_type. is_known ( db, KnownFunction :: RevealType ) {
1273
1275
CallOutcome :: revealed (
1274
- function_type. return_ty ( db) ,
1276
+ function_type. signature ( db) . return_ty ,
1275
1277
* arg_types. first ( ) . unwrap_or ( & Type :: Unknown ) ,
1276
1278
)
1277
1279
} else {
1278
- CallOutcome :: callable ( function_type. return_ty ( db) )
1280
+ CallOutcome :: callable ( function_type. signature ( db) . return_ty )
1279
1281
}
1280
1282
}
1281
1283
@@ -1461,6 +1463,24 @@ impl<'db> Type<'db> {
1461
1463
}
1462
1464
}
1463
1465
1466
+ /// If we see a value of this type used as a type expression, what type does it name?
1467
+ ///
1468
+ /// For example, the builtin `int` as a value expression is of type
1469
+ /// `Type::ClassLiteral(builtins.int)`, that is, it is the `int` class itself. As a type
1470
+ /// expression, it names the type `Type::Instance(builtins.int)`, that is, all objects whose
1471
+ /// `__class__` is `int`.
1472
+ #[ must_use]
1473
+ pub fn in_type_expression ( & self , db : & ' db dyn Db ) -> Type < ' db > {
1474
+ match self {
1475
+ Type :: ClassLiteral ( _) | Type :: SubclassOf ( _) => self . to_instance ( db) ,
1476
+ Type :: Union ( union) => union. map ( db, |element| element. in_type_expression ( db) ) ,
1477
+ Type :: Unknown => Type :: Unknown ,
1478
+ // TODO map this to a new `Type::TypeVar` variant
1479
+ Type :: KnownInstance ( KnownInstanceType :: TypeVar ( _) ) => * self ,
1480
+ _ => Type :: Todo ,
1481
+ }
1482
+ }
1483
+
1464
1484
/// The type `NoneType` / `None`
1465
1485
pub fn none ( db : & ' db dyn Db ) -> Type < ' db > {
1466
1486
KnownClass :: NoneType . to_instance ( db)
@@ -2322,7 +2342,10 @@ impl<'db> FunctionType<'db> {
2322
2342
self . decorators ( db) . contains ( & decorator)
2323
2343
}
2324
2344
2325
- /// inferred return type for this function
2345
+ /// Typed externally-visible signature for this function.
2346
+ ///
2347
+ /// This is the signature as seen by external callers, possibly modified by decorators and/or
2348
+ /// overloaded.
2326
2349
///
2327
2350
/// ## Why is this a salsa query?
2328
2351
///
@@ -2331,34 +2354,32 @@ impl<'db> FunctionType<'db> {
2331
2354
///
2332
2355
/// Were this not a salsa query, then the calling query
2333
2356
/// would depend on the function's AST and rerun for every change in that file.
2334
- #[ salsa:: tracked]
2335
- pub fn return_ty ( self , db : & ' db dyn Db ) -> Type < ' db > {
2357
+ #[ salsa:: tracked( return_ref) ]
2358
+ pub fn signature ( self , db : & ' db dyn Db ) -> Signature < ' db > {
2359
+ let function_stmt_node = self . body_scope ( db) . node ( db) . expect_function ( ) ;
2360
+ let internal_signature = self . internal_signature ( db) ;
2361
+ if function_stmt_node. decorator_list . is_empty ( ) {
2362
+ return internal_signature;
2363
+ }
2364
+ // TODO process the effect of decorators on the signature
2365
+ Signature :: todo ( )
2366
+ }
2367
+
2368
+ /// Typed internally-visible signature for this function.
2369
+ ///
2370
+ /// This represents the annotations on the function itself, unmodified by decorators and
2371
+ /// overloads.
2372
+ ///
2373
+ /// These are the parameter and return types that should be used for type checking the body of
2374
+ /// the function.
2375
+ ///
2376
+ /// Don't call this when checking any other file; only when type-checking the function body
2377
+ /// scope.
2378
+ fn internal_signature ( self , db : & ' db dyn Db ) -> Signature < ' db > {
2336
2379
let scope = self . body_scope ( db) ;
2337
2380
let function_stmt_node = scope. node ( db) . expect_function ( ) ;
2338
-
2339
- // TODO if a function `bar` is decorated by `foo`,
2340
- // where `foo` is annotated as returning a type `X` that is a subtype of `Callable`,
2341
- // we need to infer the return type from `X`'s return annotation
2342
- // rather than from `bar`'s return annotation
2343
- // in order to determine the type that `bar` returns
2344
- if !function_stmt_node. decorator_list . is_empty ( ) {
2345
- return Type :: Todo ;
2346
- }
2347
-
2348
- function_stmt_node
2349
- . returns
2350
- . as_ref ( )
2351
- . map ( |returns| {
2352
- if function_stmt_node. is_async {
2353
- // TODO: generic `types.CoroutineType`!
2354
- Type :: Todo
2355
- } else {
2356
- let definition =
2357
- semantic_index ( db, scope. file ( db) ) . definition ( function_stmt_node) ;
2358
- definition_expression_ty ( db, definition, returns. as_ref ( ) )
2359
- }
2360
- } )
2361
- . unwrap_or ( Type :: Unknown )
2381
+ let definition = semantic_index ( db, scope. file ( db) ) . definition ( function_stmt_node) ;
2382
+ Signature :: from_function ( db, definition, function_stmt_node)
2362
2383
}
2363
2384
2364
2385
pub fn is_known ( self , db : & ' db dyn Db , known_function : KnownFunction ) -> bool {
0 commit comments