@@ -1579,7 +1579,9 @@ def analyze_class(self, defn: ClassDef) -> None:
15791579 self .mark_incomplete (defn .name , defn )
15801580 return
15811581
1582- declared_metaclass , should_defer = self .get_declared_metaclass (defn .name , defn .metaclass )
1582+ declared_metaclass , should_defer , any_meta = self .get_declared_metaclass (
1583+ defn .name , defn .metaclass
1584+ )
15831585 if should_defer or self .found_incomplete_ref (tag ):
15841586 # Metaclass was not ready. Defer current target.
15851587 self .mark_incomplete (defn .name , defn )
@@ -1599,6 +1601,8 @@ def analyze_class(self, defn: ClassDef) -> None:
15991601 self .setup_type_vars (defn , tvar_defs )
16001602 if base_error :
16011603 defn .info .fallback_to_any = True
1604+ if any_meta :
1605+ defn .info .meta_fallback_to_any = True
16021606
16031607 with self .scope .class_scope (defn .info ):
16041608 self .configure_base_classes (defn , base_types )
@@ -2247,8 +2251,17 @@ def is_base_class(self, t: TypeInfo, s: TypeInfo) -> bool:
22472251
22482252 def get_declared_metaclass (
22492253 self , name : str , metaclass_expr : Expression | None
2250- ) -> tuple [Instance | None , bool ]:
2251- """Returns either metaclass instance or boolean whether we should defer."""
2254+ ) -> tuple [Instance | None , bool , bool ]:
2255+ """Get declared metaclass from metaclass expression.
2256+
2257+ Returns a tuple of three values:
2258+ * A metaclass instance or None
2259+ * A boolean indicating whether we should defer
2260+ * A boolean indicating whether we should set metaclass Any fallback
2261+ (either for Any metaclass or invalid/dynamic metaclass).
2262+
2263+ The two boolean flags can only be True if instance is None.
2264+ """
22522265 declared_metaclass = None
22532266 if metaclass_expr :
22542267 metaclass_name = None
@@ -2258,25 +2271,20 @@ def get_declared_metaclass(
22582271 metaclass_name = get_member_expr_fullname (metaclass_expr )
22592272 if metaclass_name is None :
22602273 self .fail (f'Dynamic metaclass not supported for "{ name } "' , metaclass_expr )
2261- return None , False
2274+ return None , False , True
22622275 sym = self .lookup_qualified (metaclass_name , metaclass_expr )
22632276 if sym is None :
22642277 # Probably a name error - it is already handled elsewhere
2265- return None , False
2278+ return None , False , True
22662279 if isinstance (sym .node , Var ) and isinstance (get_proper_type (sym .node .type ), AnyType ):
2267- # Create a fake TypeInfo that fallbacks to `Any`, basically allowing
2268- # all the attributes. Same thing as we do for `Any` base class.
2269- any_info = self .make_empty_type_info (ClassDef (sym .node .name , Block ([])))
2270- any_info .fallback_to_any = True
2271- any_info ._fullname = sym .node .fullname
22722280 if self .options .disallow_subclassing_any :
22732281 self .fail (
2274- f'Class cannot use "{ any_info . fullname } " as a metaclass (has type "Any")' ,
2282+ f'Class cannot use "{ sym . node . name } " as a metaclass (has type "Any")' ,
22752283 metaclass_expr ,
22762284 )
2277- return Instance ( any_info , []), False
2285+ return None , False , True
22782286 if isinstance (sym .node , PlaceholderNode ):
2279- return None , True # defer later in the caller
2287+ return None , True , False # defer later in the caller
22802288
22812289 # Support type aliases, like `_Meta: TypeAlias = type`
22822290 if (
@@ -2291,16 +2299,16 @@ def get_declared_metaclass(
22912299
22922300 if not isinstance (metaclass_info , TypeInfo ) or metaclass_info .tuple_type is not None :
22932301 self .fail (f'Invalid metaclass "{ metaclass_name } "' , metaclass_expr )
2294- return None , False
2302+ return None , False , False
22952303 if not metaclass_info .is_metaclass ():
22962304 self .fail (
22972305 'Metaclasses not inheriting from "type" are not supported' , metaclass_expr
22982306 )
2299- return None , False
2307+ return None , False , False
23002308 inst = fill_typevars (metaclass_info )
23012309 assert isinstance (inst , Instance )
23022310 declared_metaclass = inst
2303- return declared_metaclass , False
2311+ return declared_metaclass , False , False
23042312
23052313 def recalculate_metaclass (self , defn : ClassDef , declared_metaclass : Instance | None ) -> None :
23062314 defn .info .declared_metaclass = declared_metaclass
0 commit comments