@@ -108,23 +108,18 @@ enum DataclassFieldsPolicy {
108108}
109109
110110impl DataclassFieldsPolicy {
111- fn matches < ' db > (
112- self ,
113- db : & ' db dyn Db ,
114- class : ClassLiteral < ' db > ,
115- specialization : Option < Specialization < ' db > > ,
116- ) -> bool {
111+ fn matches < ' db > ( self , db : & ' db dyn Db , class : ClassLiteral < ' db > ) -> bool {
117112 match self {
118113 Self :: Dataclass => {
119114 class. dataclass_params ( db) . is_some ( )
120115 || class
121116 . try_metaclass ( db)
122117 . is_ok_and ( |( _, transformer_params) | transformer_params. is_some ( ) )
123118 }
124- Self :: NamedTuple => KnownClass :: NamedTuple
125- . to_class_literal ( db )
126- . to_class_type ( db )
127- . is_some_and ( |named_tuple| class . is_subclass_of ( db , specialization , named_tuple ) ) ,
119+ Self :: NamedTuple => class . explicit_bases ( db ) . iter ( ) . any ( |base| {
120+ base . into_class_literal ( )
121+ . is_some_and ( |c| c . is_known ( db , KnownClass :: NamedTuple ) )
122+ } ) ,
128123 }
129124 }
130125}
@@ -1016,12 +1011,6 @@ impl<'db> ClassLiteral<'db> {
10161011
10171012 if symbol. symbol . is_unbound ( ) {
10181013 if let Some ( dataclass_member) = self . own_dataclass_member ( db, specialization, name) {
1019- eprintln ! (
1020- "==> dataclass {} {} {}" ,
1021- Type :: from( self ) . display( db) ,
1022- name,
1023- dataclass_member. display( db)
1024- ) ;
10251014 return Symbol :: bound ( dataclass_member) . into ( ) ;
10261015 }
10271016 }
@@ -1038,21 +1027,21 @@ impl<'db> ClassLiteral<'db> {
10381027 ) -> Option < Type < ' db > > {
10391028 let params = self . dataclass_params ( db) ;
10401029 let has_dataclass_param = |param| params. is_some_and ( |params| params. contains ( param) ) ;
1030+ let field_policy = if has_dataclass_param ( DataclassParams :: INIT )
1031+ || self
1032+ . try_metaclass ( db)
1033+ . is_ok_and ( |( _, transformer_params) | transformer_params. is_some ( ) )
1034+ {
1035+ DataclassFieldsPolicy :: Dataclass
1036+ } else if DataclassFieldsPolicy :: NamedTuple . matches ( db, self ) {
1037+ DataclassFieldsPolicy :: NamedTuple
1038+ } else {
1039+ return None ;
1040+ } ;
10411041
1042- match name {
1043- "__init__" => {
1044- let field_policy = if has_dataclass_param ( DataclassParams :: INIT )
1045- || self
1046- . try_metaclass ( db)
1047- . is_ok_and ( |( _, transformer_params) | transformer_params. is_some ( ) )
1048- {
1049- DataclassFieldsPolicy :: Dataclass
1050- } else if DataclassFieldsPolicy :: NamedTuple . matches ( db, self , specialization) {
1051- DataclassFieldsPolicy :: NamedTuple
1052- } else {
1053- return None ;
1054- } ;
1055-
1042+ match ( name, field_policy) {
1043+ ( "__init__" , DataclassFieldsPolicy :: Dataclass )
1044+ | ( "__new__" , DataclassFieldsPolicy :: NamedTuple ) => {
10561045 let mut parameters = vec ! [ ] ;
10571046
10581047 for ( name, ( mut attr_ty, mut default_ty) ) in
@@ -1118,12 +1107,20 @@ impl<'db> ClassLiteral<'db> {
11181107 parameters. push ( parameter) ;
11191108 }
11201109
1121- let init_signature =
1122- Signature :: new ( Parameters :: new ( parameters) , Some ( Type :: none ( db) ) ) ;
1110+ if name == "__init__" {
1111+ let init_signature =
1112+ Signature :: new ( Parameters :: new ( parameters) , Some ( Type :: none ( db) ) ) ;
11231113
1124- Some ( Type :: Callable ( CallableType :: single ( db, init_signature) ) )
1114+ Some ( Type :: Callable ( CallableType :: single ( db, init_signature) ) )
1115+ } else {
1116+ parameters. insert ( 0 , Parameter :: positional_or_keyword ( Name :: new_static ( "cls" ) ) ) ;
1117+ let new_signature =
1118+ Signature :: new ( Parameters :: new ( parameters) , Some ( Type :: none ( db) ) ) ;
1119+
1120+ Some ( Type :: Callable ( CallableType :: single ( db, new_signature) ) )
1121+ }
11251122 }
1126- "__lt__" | "__le__" | "__gt__" | "__ge__" => {
1123+ ( "__lt__" | "__le__" | "__gt__" | "__ge__" , DataclassFieldsPolicy :: Dataclass ) => {
11271124 if !has_dataclass_param ( DataclassParams :: ORDER ) {
11281125 return None ;
11291126 }
@@ -1144,13 +1141,6 @@ impl<'db> ClassLiteral<'db> {
11441141 }
11451142 }
11461143
1147- fn is_dataclass ( self , db : & ' db dyn Db ) -> bool {
1148- self . dataclass_params ( db) . is_some ( )
1149- || self
1150- . try_metaclass ( db)
1151- . is_ok_and ( |( _, transformer_params) | transformer_params. is_some ( ) )
1152- }
1153-
11541144 /// Returns a list of all annotated attributes defined in this class, or any of its superclasses.
11551145 ///
11561146 /// See [`ClassLiteral::own_dataclass_fields`] for more details.
@@ -1165,7 +1155,7 @@ impl<'db> ClassLiteral<'db> {
11651155 . filter_map ( |superclass| {
11661156 if let Some ( class) = superclass. into_class ( ) {
11671157 let class_literal = class. class_literal ( db) . 0 ;
1168- if field_policy. matches ( db, class_literal, specialization ) {
1158+ if field_policy. matches ( db, class_literal) {
11691159 Some ( class_literal)
11701160 } else {
11711161 None
@@ -2113,6 +2103,7 @@ impl<'db> KnownClass {
21132103 | Self :: TypeVarTuple
21142104 | Self :: TypeAliasType
21152105 | Self :: NoDefaultType
2106+ | Self :: NamedTuple
21162107 | Self :: NewType
21172108 | Self :: ChainMap
21182109 | Self :: Counter
0 commit comments