@@ -759,6 +759,10 @@ impl<'db> Type<'db> {
759
759
. expect ( "Expected a Type::Intersection variant" )
760
760
}
761
761
762
+ pub ( crate ) fn function_literal ( db : & ' db dyn Db , function : FunctionLiteral < ' db > ) -> Self {
763
+ Self :: FunctionLiteral ( FunctionType :: new ( db, function, None , None ) )
764
+ }
765
+
762
766
pub const fn into_function_literal ( self ) -> Option < FunctionType < ' db > > {
763
767
match self {
764
768
Type :: FunctionLiteral ( function_type) => Some ( function_type) ,
@@ -6059,6 +6063,25 @@ impl<'db> FunctionSignature<'db> {
6059
6063
pub ( crate ) fn iter ( & self ) -> Iter < Signature < ' db > > {
6060
6064
self . as_slice ( ) . iter ( )
6061
6065
}
6066
+
6067
+ fn iter_mut ( & mut self ) -> impl Iterator < Item = & mut Signature < ' db > > {
6068
+ match self {
6069
+ Self :: Single ( signature) => std:: slice:: from_mut ( signature) . iter_mut ( ) ,
6070
+ Self :: Overloaded ( signatures, _) => signatures. iter_mut ( ) ,
6071
+ }
6072
+ }
6073
+
6074
+ fn set_inherited_generic_context ( & mut self , inherited_generic_context : GenericContext < ' db > ) {
6075
+ self . iter_mut ( ) . for_each ( |signature| {
6076
+ signature. set_inherited_generic_context ( inherited_generic_context) ;
6077
+ } ) ;
6078
+ }
6079
+
6080
+ fn apply_specialization ( & mut self , db : & ' db dyn Db , specialization : Specialization < ' db > ) {
6081
+ self . iter_mut ( ) . for_each ( |signature| {
6082
+ signature. apply_specialization ( db, specialization) ;
6083
+ } ) ;
6084
+ }
6062
6085
}
6063
6086
6064
6087
impl < ' db > IntoIterator for & ' db FunctionSignature < ' db > {
@@ -6072,22 +6095,7 @@ impl<'db> IntoIterator for &'db FunctionSignature<'db> {
6072
6095
6073
6096
#[ salsa:: interned( debug) ]
6074
6097
pub struct FunctionType < ' db > {
6075
- /// Name of the function at definition.
6076
- #[ return_ref]
6077
- pub name : ast:: name:: Name ,
6078
-
6079
- /// Is this a function that we special-case somehow? If so, which one?
6080
- known : Option < KnownFunction > ,
6081
-
6082
- /// The scope that's created by the function, in which the function body is evaluated.
6083
- body_scope : ScopeId < ' db > ,
6084
-
6085
- /// A set of special decorators that were applied to this function
6086
- decorators : FunctionDecorators ,
6087
-
6088
- /// The arguments to `dataclass_transformer`, if this function was annotated
6089
- /// with `@dataclass_transformer(...)`.
6090
- dataclass_transformer_params : Option < DataclassTransformerParams > ,
6098
+ function : FunctionLiteral < ' db > ,
6091
6099
6092
6100
/// The inherited generic context, if this function is a class method being used to infer the
6093
6101
/// specialization of its generic class. If the method is itself generic, this is in addition
@@ -6103,7 +6111,7 @@ pub struct FunctionType<'db> {
6103
6111
#[ salsa:: tracked]
6104
6112
impl < ' db > FunctionType < ' db > {
6105
6113
pub ( crate ) fn has_known_decorator ( self , db : & dyn Db , decorator : FunctionDecorators ) -> bool {
6106
- self . decorators ( db) . contains ( decorator)
6114
+ self . function ( db) . has_known_decorator ( db , decorator)
6107
6115
}
6108
6116
6109
6117
/// Convert the `FunctionType` into a [`Type::Callable`].
@@ -6123,25 +6131,29 @@ impl<'db> FunctionType<'db> {
6123
6131
Type :: BoundMethod ( BoundMethodType :: new ( db, self , self_instance) )
6124
6132
}
6125
6133
6134
+ pub fn name ( self , db : & ' db dyn Db ) -> & ' db ast:: name:: Name {
6135
+ self . function ( db) . name ( db)
6136
+ }
6137
+
6126
6138
/// Returns the [`FileRange`] of the function's name.
6127
6139
pub fn focus_range ( self , db : & dyn Db ) -> FileRange {
6140
+ let body_scope = self . function ( db) . body_scope ( db) ;
6128
6141
FileRange :: new (
6129
- self . body_scope ( db ) . file ( db) ,
6130
- self . body_scope ( db ) . node ( db) . expect_function ( ) . name . range ,
6142
+ body_scope. file ( db) ,
6143
+ body_scope. node ( db) . expect_function ( ) . name . range ,
6131
6144
)
6132
6145
}
6133
6146
6134
6147
pub fn full_range ( self , db : & dyn Db ) -> FileRange {
6148
+ let body_scope = self . function ( db) . body_scope ( db) ;
6135
6149
FileRange :: new (
6136
- self . body_scope ( db ) . file ( db) ,
6137
- self . body_scope ( db ) . node ( db) . expect_function ( ) . range ,
6150
+ body_scope. file ( db) ,
6151
+ body_scope. node ( db) . expect_function ( ) . range ,
6138
6152
)
6139
6153
}
6140
6154
6141
6155
pub ( crate ) fn definition ( self , db : & ' db dyn Db ) -> Definition < ' db > {
6142
- let body_scope = self . body_scope ( db) ;
6143
- let index = semantic_index ( db, body_scope. file ( db) ) ;
6144
- index. expect_single_definition ( body_scope. node ( db) . expect_function ( ) )
6156
+ self . function ( db) . definition ( db)
6145
6157
}
6146
6158
6147
6159
/// Typed externally-visible signature for this function.
@@ -6158,6 +6170,114 @@ impl<'db> FunctionType<'db> {
6158
6170
/// would depend on the function's AST and rerun for every change in that file.
6159
6171
#[ salsa:: tracked( return_ref) ]
6160
6172
pub ( crate ) fn signature ( self , db : & ' db dyn Db ) -> FunctionSignature < ' db > {
6173
+ let mut signature = self . function ( db) . signature ( db) . clone ( ) ;
6174
+ if let Some ( inherited_generic_context) = self . inherited_generic_context ( db) {
6175
+ signature. set_inherited_generic_context ( inherited_generic_context) ;
6176
+ }
6177
+ if let Some ( specialization) = self . specialization ( db) {
6178
+ signature. apply_specialization ( db, specialization) ;
6179
+ }
6180
+ signature
6181
+ }
6182
+
6183
+ pub ( crate ) fn known ( self , db : & ' db dyn Db ) -> Option < KnownFunction > {
6184
+ self . function ( db) . known ( db)
6185
+ }
6186
+
6187
+ pub ( crate ) fn is_known ( self , db : & ' db dyn Db , known_function : KnownFunction ) -> bool {
6188
+ self . known ( db) == Some ( known_function)
6189
+ }
6190
+
6191
+ fn with_dataclass_transformer_params (
6192
+ self ,
6193
+ db : & ' db dyn Db ,
6194
+ params : DataclassTransformerParams ,
6195
+ ) -> Self {
6196
+ let function = self
6197
+ . function ( db)
6198
+ . with_dataclass_transformer_params ( db, params) ;
6199
+ Self :: new (
6200
+ db,
6201
+ function,
6202
+ self . inherited_generic_context ( db) ,
6203
+ self . specialization ( db) ,
6204
+ )
6205
+ }
6206
+
6207
+ fn with_inherited_generic_context (
6208
+ self ,
6209
+ db : & ' db dyn Db ,
6210
+ inherited_generic_context : GenericContext < ' db > ,
6211
+ ) -> Self {
6212
+ // A function cannot inherit more than one generic context from its containing class.
6213
+ debug_assert ! ( self . inherited_generic_context( db) . is_none( ) ) ;
6214
+ Self :: new (
6215
+ db,
6216
+ self . function ( db) ,
6217
+ Some ( inherited_generic_context) ,
6218
+ self . specialization ( db) ,
6219
+ )
6220
+ }
6221
+
6222
+ fn apply_specialization ( self , db : & ' db dyn Db , specialization : Specialization < ' db > ) -> Self {
6223
+ let specialization = match self . specialization ( db) {
6224
+ Some ( existing) => existing. apply_specialization ( db, specialization) ,
6225
+ None => specialization,
6226
+ } ;
6227
+ Self :: new (
6228
+ db,
6229
+ self . function ( db) ,
6230
+ self . inherited_generic_context ( db) ,
6231
+ Some ( specialization) ,
6232
+ )
6233
+ }
6234
+
6235
+ fn find_legacy_typevars (
6236
+ self ,
6237
+ db : & ' db dyn Db ,
6238
+ typevars : & mut FxOrderSet < TypeVarInstance < ' db > > ,
6239
+ ) {
6240
+ let signatures = self . signature ( db) ;
6241
+ for signature in signatures {
6242
+ signature. find_legacy_typevars ( db, typevars) ;
6243
+ }
6244
+ }
6245
+ }
6246
+
6247
+ #[ salsa:: interned( debug) ]
6248
+ pub struct FunctionLiteral < ' db > {
6249
+ /// Name of the function at definition.
6250
+ #[ return_ref]
6251
+ pub name : ast:: name:: Name ,
6252
+
6253
+ /// Is this a function that we special-case somehow? If so, which one?
6254
+ known : Option < KnownFunction > ,
6255
+
6256
+ /// The scope that's created by the function, in which the function body is evaluated.
6257
+ body_scope : ScopeId < ' db > ,
6258
+
6259
+ /// A set of special decorators that were applied to this function
6260
+ decorators : FunctionDecorators ,
6261
+
6262
+ /// The arguments to `dataclass_transformer`, if this function was annotated
6263
+ /// with `@dataclass_transformer(...)`.
6264
+ dataclass_transformer_params : Option < DataclassTransformerParams > ,
6265
+ }
6266
+
6267
+ #[ salsa:: tracked]
6268
+ impl < ' db > FunctionLiteral < ' db > {
6269
+ fn has_known_decorator ( self , db : & dyn Db , decorator : FunctionDecorators ) -> bool {
6270
+ self . decorators ( db) . contains ( decorator)
6271
+ }
6272
+
6273
+ fn definition ( self , db : & ' db dyn Db ) -> Definition < ' db > {
6274
+ let body_scope = self . body_scope ( db) ;
6275
+ let index = semantic_index ( db, body_scope. file ( db) ) ;
6276
+ index. expect_single_definition ( body_scope. node ( db) . expect_function ( ) )
6277
+ }
6278
+
6279
+ #[ salsa:: tracked( return_ref) ]
6280
+ fn signature ( self , db : & ' db dyn Db ) -> FunctionSignature < ' db > {
6161
6281
let internal_signature = self . internal_signature ( db) ;
6162
6282
6163
6283
// The semantic model records a use for each function on the name node. This is used here
@@ -6222,21 +6342,7 @@ impl<'db> FunctionType<'db> {
6222
6342
let index = semantic_index ( db, scope. file ( db) ) ;
6223
6343
GenericContext :: from_type_params ( db, index, type_params)
6224
6344
} ) ;
6225
- let mut signature = Signature :: from_function (
6226
- db,
6227
- generic_context,
6228
- self . inherited_generic_context ( db) ,
6229
- definition,
6230
- function_stmt_node,
6231
- ) ;
6232
- if let Some ( specialization) = self . specialization ( db) {
6233
- signature = signature. apply_specialization ( db, specialization) ;
6234
- }
6235
- signature
6236
- }
6237
-
6238
- pub ( crate ) fn is_known ( self , db : & ' db dyn Db , known_function : KnownFunction ) -> bool {
6239
- self . known ( db) == Some ( known_function)
6345
+ Signature :: from_function ( db, generic_context, definition, function_stmt_node)
6240
6346
}
6241
6347
6242
6348
fn with_dataclass_transformer_params (
@@ -6251,57 +6357,8 @@ impl<'db> FunctionType<'db> {
6251
6357
self . body_scope ( db) ,
6252
6358
self . decorators ( db) ,
6253
6359
Some ( params) ,
6254
- self . inherited_generic_context ( db) ,
6255
- self . specialization ( db) ,
6256
- )
6257
- }
6258
-
6259
- fn with_inherited_generic_context (
6260
- self ,
6261
- db : & ' db dyn Db ,
6262
- inherited_generic_context : GenericContext < ' db > ,
6263
- ) -> Self {
6264
- // A function cannot inherit more than one generic context from its containing class.
6265
- debug_assert ! ( self . inherited_generic_context( db) . is_none( ) ) ;
6266
- Self :: new (
6267
- db,
6268
- self . name ( db) . clone ( ) ,
6269
- self . known ( db) ,
6270
- self . body_scope ( db) ,
6271
- self . decorators ( db) ,
6272
- self . dataclass_transformer_params ( db) ,
6273
- Some ( inherited_generic_context) ,
6274
- self . specialization ( db) ,
6275
- )
6276
- }
6277
-
6278
- fn apply_specialization ( self , db : & ' db dyn Db , specialization : Specialization < ' db > ) -> Self {
6279
- let specialization = match self . specialization ( db) {
6280
- Some ( existing) => existing. apply_specialization ( db, specialization) ,
6281
- None => specialization,
6282
- } ;
6283
- Self :: new (
6284
- db,
6285
- self . name ( db) . clone ( ) ,
6286
- self . known ( db) ,
6287
- self . body_scope ( db) ,
6288
- self . decorators ( db) ,
6289
- self . dataclass_transformer_params ( db) ,
6290
- self . inherited_generic_context ( db) ,
6291
- Some ( specialization) ,
6292
6360
)
6293
6361
}
6294
-
6295
- fn find_legacy_typevars (
6296
- self ,
6297
- db : & ' db dyn Db ,
6298
- typevars : & mut FxOrderSet < TypeVarInstance < ' db > > ,
6299
- ) {
6300
- let signatures = self . signature ( db) ;
6301
- for signature in signatures {
6302
- signature. find_legacy_typevars ( db, typevars) ;
6303
- }
6304
- }
6305
6362
}
6306
6363
6307
6364
/// Non-exhaustive enumeration of known functions (e.g. `builtins.reveal_type`, ...) that might
@@ -6519,9 +6576,11 @@ impl<'db> CallableType<'db> {
6519
6576
fn apply_specialization ( self , db : & ' db dyn Db , specialization : Specialization < ' db > ) -> Self {
6520
6577
CallableType :: from_overloads (
6521
6578
db,
6522
- self . signatures ( db)
6523
- . iter ( )
6524
- . map ( |signature| signature. apply_specialization ( db, specialization) ) ,
6579
+ self . signatures ( db) . iter ( ) . map ( |signature| {
6580
+ let mut signature = signature. clone ( ) ;
6581
+ signature. apply_specialization ( db, specialization) ;
6582
+ signature
6583
+ } ) ,
6525
6584
)
6526
6585
}
6527
6586
0 commit comments