@@ -156,14 +156,6 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
156
156
// this does not turn the class into a dataclass! Instead, it becomes a special base class
157
157
// (or metaclass) that turns child classes into dataclasses.
158
158
let mut dataclass_transform_metadata = dataclass_defaults_from_base_class. clone ( ) ;
159
- // If we inherit from a dataclass, inherit its metadata. Note that if this class is
160
- // itself decorated with @dataclass, we'll compute new metadata and overwrite this.
161
- let mut dataclass_metadata = bases_with_metadata. iter ( ) . find_map ( |( _, metadata) | {
162
- let mut m = metadata. dataclass_metadata ( ) . cloned ( ) ?;
163
- // Avoid accidentally overwriting a non-synthesized `__init__`.
164
- m. kws . init = false ;
165
- Some ( m)
166
- } ) ;
167
159
// This is set when we should apply dataclass-like transformations to the class. The class
168
160
// should be transformed if:
169
161
// - it inherits from a base class decorated with `dataclass_transform(...)`, or
@@ -246,44 +238,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
246
238
}
247
239
let mut is_final = false ;
248
240
let mut total_ordering_metadata = None ;
249
- for ( decorator, decorator_range) in decorators {
241
+ for ( decorator, decorator_range) in decorators. iter ( ) {
250
242
let decorator_ty = decorator. ty ( ) ;
251
243
match decorator_ty. callee_kind ( ) {
252
244
Some ( CalleeKind :: Function ( FunctionKind :: Final ) ) => {
253
245
is_final = true ;
254
246
}
255
247
Some ( CalleeKind :: Function ( FunctionKind :: TotalOrdering ) ) => {
256
248
total_ordering_metadata = Some ( TotalOrderingMetadata {
257
- location : decorator_range,
258
- } ) ;
259
- }
260
- // `@dataclass`
261
- Some ( CalleeKind :: Function ( FunctionKind :: Dataclass ) ) => {
262
- let dataclass_fields = self . get_dataclass_fields ( cls, & bases_with_metadata) ;
263
- dataclass_metadata = Some ( DataclassMetadata {
264
- fields : dataclass_fields,
265
- kws : DataclassKeywords :: new ( ) ,
266
- field_specifiers : vec ! [
267
- CalleeKind :: Function ( FunctionKind :: DataclassField ) ,
268
- CalleeKind :: Class ( ClassKind :: DataclassField ) ,
269
- ] ,
270
- } ) ;
271
- }
272
- // `@dataclass(...)`
273
- _ if let Type :: KwCall ( call) = decorator_ty
274
- && call. has_function_kind ( FunctionKind :: Dataclass ) =>
275
- {
276
- let dataclass_fields = self . get_dataclass_fields ( cls, & bases_with_metadata) ;
277
- dataclass_metadata = Some ( DataclassMetadata {
278
- fields : dataclass_fields,
279
- kws : DataclassKeywords :: from_type_map (
280
- & call. keywords ,
281
- & DataclassTransformKeywords :: new ( ) ,
282
- ) ,
283
- field_specifiers : vec ! [
284
- CalleeKind :: Function ( FunctionKind :: DataclassField ) ,
285
- CalleeKind :: Class ( ClassKind :: DataclassField ) ,
286
- ] ,
249
+ location : * decorator_range,
287
250
} ) ;
288
251
}
289
252
// `@dataclass_transform(...)`
@@ -313,13 +276,12 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
313
276
_ => { }
314
277
}
315
278
}
316
- if let Some ( ( kws, field_specifiers) ) = dataclass_from_dataclass_transform {
317
- dataclass_metadata = Some ( DataclassMetadata {
318
- fields : self . get_dataclass_fields ( cls, & bases_with_metadata) ,
319
- kws,
320
- field_specifiers,
321
- } ) ;
322
- }
279
+ let dataclass_metadata = self . dataclass_metadata (
280
+ cls,
281
+ & decorators,
282
+ & bases_with_metadata,
283
+ dataclass_from_dataclass_transform,
284
+ ) ;
323
285
if let Some ( dm) = dataclass_metadata. as_ref ( ) {
324
286
self . validate_frozen_dataclass_inheritance ( cls, dm, & bases_with_metadata, errors) ;
325
287
}
@@ -542,6 +504,66 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
542
504
}
543
505
}
544
506
507
+ fn dataclass_metadata (
508
+ & self ,
509
+ cls : & Class ,
510
+ decorators : & [ ( Arc < TypeInfo > , TextRange ) ] ,
511
+ bases_with_metadata : & [ ( Class , Arc < ClassMetadata > ) ] ,
512
+ dataclass_from_dataclass_transform : Option < ( DataclassKeywords , Vec < CalleeKind > ) > ,
513
+ ) -> Option < DataclassMetadata > {
514
+ // If we inherit from a dataclass, inherit its metadata. Note that if this class is
515
+ // itself decorated with @dataclass, we'll compute new metadata and overwrite this.
516
+ let mut dataclass_metadata = bases_with_metadata. iter ( ) . find_map ( |( _, metadata) | {
517
+ let mut m = metadata. dataclass_metadata ( ) . cloned ( ) ?;
518
+ // Avoid accidentally overwriting a non-synthesized `__init__`.
519
+ m. kws . init = false ;
520
+ Some ( m)
521
+ } ) ;
522
+ for ( decorator, _) in decorators {
523
+ let decorator_ty = decorator. ty ( ) ;
524
+ match decorator_ty. callee_kind ( ) {
525
+ // `@dataclass`
526
+ Some ( CalleeKind :: Function ( FunctionKind :: Dataclass ) ) => {
527
+ let dataclass_fields = self . get_dataclass_fields ( cls, bases_with_metadata) ;
528
+ dataclass_metadata = Some ( DataclassMetadata {
529
+ fields : dataclass_fields,
530
+ kws : DataclassKeywords :: new ( ) ,
531
+ field_specifiers : vec ! [
532
+ CalleeKind :: Function ( FunctionKind :: DataclassField ) ,
533
+ CalleeKind :: Class ( ClassKind :: DataclassField ) ,
534
+ ] ,
535
+ } ) ;
536
+ }
537
+ // `@dataclass(...)`
538
+ _ if let Type :: KwCall ( call) = decorator_ty
539
+ && call. has_function_kind ( FunctionKind :: Dataclass ) =>
540
+ {
541
+ let dataclass_fields = self . get_dataclass_fields ( cls, bases_with_metadata) ;
542
+ dataclass_metadata = Some ( DataclassMetadata {
543
+ fields : dataclass_fields,
544
+ kws : DataclassKeywords :: from_type_map (
545
+ & call. keywords ,
546
+ & DataclassTransformKeywords :: new ( ) ,
547
+ ) ,
548
+ field_specifiers : vec ! [
549
+ CalleeKind :: Function ( FunctionKind :: DataclassField ) ,
550
+ CalleeKind :: Class ( ClassKind :: DataclassField ) ,
551
+ ] ,
552
+ } ) ;
553
+ }
554
+ _ => { }
555
+ }
556
+ }
557
+ if let Some ( ( kws, field_specifiers) ) = dataclass_from_dataclass_transform {
558
+ dataclass_metadata = Some ( DataclassMetadata {
559
+ fields : self . get_dataclass_fields ( cls, bases_with_metadata) ,
560
+ kws,
561
+ field_specifiers,
562
+ } ) ;
563
+ }
564
+ dataclass_metadata
565
+ }
566
+
545
567
// To avoid circular computation on targs, we have a special version of `expr_infer` that only recognize a small
546
568
// subset of syntactical forms, and does not look into any subscript of any expr
547
569
fn base_class_expr_infer ( & self , expr : & Expr , errors : & ErrorCollector ) -> Option < Type > {
0 commit comments