@@ -102,9 +102,13 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
102102 pydantic_metadata_binding : & PydanticMetadataBinding ,
103103 errors : & ErrorCollector ,
104104 ) -> ClassMetadata {
105+ // Get class decorators.
105106 let decorators = decorators. map ( |( decorator_key, decorator_range) | {
106107 ( self . get_idx ( * decorator_key) , * decorator_range)
107108 } ) ;
109+
110+ // Get full base class list and compute data that depends on the `BaseClass` representation
111+ // of base classes.
108112 let bases = if let Some ( special_base) = special_base {
109113 bases
110114 . iter ( )
@@ -118,6 +122,8 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
118122 let has_generic_base_class = bases. iter ( ) . any ( |x| x. is_generic ( ) ) ;
119123 let has_typed_dict_base_class = bases. iter ( ) . any ( |x| x. is_typed_dict ( ) ) ;
120124
125+ // Parse base classes and compute data that depends on the `BaseClassParseResult`
126+ // representation of base classes.
121127 let parsed_results = bases
122128 . into_iter ( )
123129 . map ( |x| self . parse_base_class ( x, is_new_type) )
@@ -129,44 +135,16 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
129135 & parsed_results,
130136 errors,
131137 ) ;
138+
139+ // Compute base classes with metadata.
132140 let bases_with_metadata = self . bases_with_metadata ( parsed_results, is_new_type, errors) ;
133- let has_base_any = contains_base_class_any
134- || bases_with_metadata
135- . iter ( )
136- . any ( |( _, metadata) | metadata. has_base_any ( ) ) ;
137141
138- let named_tuple_metadata = self . named_tuple_metadata ( cls, & bases_with_metadata, errors) ;
139- if named_tuple_metadata. is_some ( ) && bases_with_metadata. len ( ) > 1 {
140- self . error (
141- errors,
142- cls. range ( ) ,
143- ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
144- "Named tuples do not support multiple inheritance" . to_owned ( ) ,
145- ) ;
146- }
142+ // Compute class keywords, including the metaclass.
147143 let ( metaclasses, keywords) : ( Vec < _ > , Vec < ( _ , _ ) > ) =
148144 keywords. iter ( ) . partition_map ( |( n, x) | match n. as_str ( ) {
149145 "metaclass" => Either :: Left ( x) ,
150146 _ => Either :: Right ( ( n. clone ( ) , self . expr_infer ( x, errors) ) ) ,
151147 } ) ;
152- let pydantic_metadata =
153- self . pydantic_metadata ( & bases_with_metadata, pydantic_metadata_binding) ;
154-
155- let is_typed_dict = has_typed_dict_base_class
156- || bases_with_metadata
157- . iter ( )
158- . any ( |( _, metadata) | metadata. is_typed_dict ( ) ) ;
159- if is_typed_dict
160- && let Some ( bad) = bases_with_metadata. iter ( ) . find ( |x| !x. 1 . is_typed_dict ( ) )
161- {
162- self . error ( errors,
163- cls. range ( ) ,
164- ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
165- format ! ( "`{}` is not a typed dictionary. Typed dictionary definitions may only extend other typed dictionaries." , bad. 0 . name( ) ) ,
166- ) ;
167- }
168- let typed_dict_metadata =
169- self . typed_dict_metadata ( cls, & bases_with_metadata, & keywords, is_typed_dict, errors) ;
170148 let base_metaclasses = bases_with_metadata
171149 . iter ( )
172150 . filter_map ( |( b, metadata) | metadata. metaclass ( ) . map ( |m| ( b. name ( ) , m) ) )
@@ -177,18 +155,8 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
177155 & base_metaclasses,
178156 errors,
179157 ) ;
180- let enum_metadata =
181- self . enum_metadata ( cls, metaclass. as_ref ( ) , & bases_with_metadata, errors) ;
182158 if let Some ( metaclass) = & metaclass {
183159 self . check_base_class_metaclasses ( cls, metaclass, & base_metaclasses, errors) ;
184- if is_typed_dict {
185- self . error (
186- errors,
187- cls. range ( ) ,
188- ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
189- "Typed dictionary definitions may not specify a metaclass" . to_owned ( ) ,
190- ) ;
191- }
192160 if metaclass. targs ( ) . as_slice ( ) . iter ( ) . any ( |targ| {
193161 targ. any ( |ty| {
194162 matches ! (
@@ -205,9 +173,57 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
205173 ) ;
206174 }
207175 }
176+
177+ // Compute various pieces of special metadata.
178+ let has_base_any = contains_base_class_any
179+ || bases_with_metadata
180+ . iter ( )
181+ . any ( |( _, metadata) | metadata. has_base_any ( ) ) ;
182+
183+ let named_tuple_metadata = self . named_tuple_metadata ( cls, & bases_with_metadata, errors) ;
184+ if named_tuple_metadata. is_some ( ) && bases_with_metadata. len ( ) > 1 {
185+ self . error (
186+ errors,
187+ cls. range ( ) ,
188+ ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
189+ "Named tuples do not support multiple inheritance" . to_owned ( ) ,
190+ ) ;
191+ }
192+
193+ let pydantic_metadata =
194+ self . pydantic_metadata ( & bases_with_metadata, pydantic_metadata_binding) ;
195+
196+ let is_typed_dict = has_typed_dict_base_class
197+ || bases_with_metadata
198+ . iter ( )
199+ . any ( |( _, metadata) | metadata. is_typed_dict ( ) ) ;
200+ if is_typed_dict
201+ && let Some ( bad) = bases_with_metadata. iter ( ) . find ( |x| !x. 1 . is_typed_dict ( ) )
202+ {
203+ self . error ( errors,
204+ cls. range ( ) ,
205+ ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
206+ format ! ( "`{}` is not a typed dictionary. Typed dictionary definitions may only extend other typed dictionaries." , bad. 0 . name( ) ) ,
207+ ) ;
208+ }
209+ let typed_dict_metadata =
210+ self . typed_dict_metadata ( cls, & bases_with_metadata, & keywords, is_typed_dict, errors) ;
211+ if metaclass. is_some ( ) && is_typed_dict {
212+ self . error (
213+ errors,
214+ cls. range ( ) ,
215+ ErrorInfo :: Kind ( ErrorKind :: InvalidInheritance ) ,
216+ "Typed dictionary definitions may not specify a metaclass" . to_owned ( ) ,
217+ ) ;
218+ }
219+
220+ let enum_metadata =
221+ self . enum_metadata ( cls, metaclass. as_ref ( ) , & bases_with_metadata, errors) ;
222+
208223 let is_final = decorators. iter ( ) . any ( |( decorator, _) | {
209224 decorator. ty ( ) . callee_kind ( ) == Some ( CalleeKind :: Function ( FunctionKind :: Final ) )
210225 } ) ;
226+
211227 let total_ordering_metadata = decorators. iter ( ) . find_map ( |( decorator, decorator_range) | {
212228 decorator. ty ( ) . callee_kind ( ) . and_then ( |kind| {
213229 if kind == CalleeKind :: Function ( FunctionKind :: TotalOrdering ) {
@@ -219,6 +235,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
219235 }
220236 } )
221237 } ) ;
238+
222239 // If this class inherits from a dataclass_transform-ed class, record the defaults that we
223240 // should use for dataclass parameters.
224241 let dataclass_defaults_from_base_class = bases_with_metadata
@@ -245,6 +262,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
245262 self . validate_frozen_dataclass_inheritance ( cls, dm, & bases_with_metadata, errors) ;
246263 }
247264
265+ // Compute final base class list.
248266 let bases = if is_typed_dict && bases_with_metadata. is_empty ( ) {
249267 // This is a "fallback" class that contains attributes that are available on all TypedDict subclasses.
250268 // Note that this also makes those attributes available on *instances* of said subclasses; this is
0 commit comments