@@ -308,18 +308,21 @@ def report_missing_attribute(
308308def analyze_instance_member_access (
309309 name : str , typ : Instance , mx : MemberContext , override_info : TypeInfo | None
310310) -> Type :
311- if name == "__init__" and not mx .is_super :
312- # Accessing __init__ in statically typed code would compromise
313- # type safety unless used via super().
314- mx .fail (message_registry .CANNOT_ACCESS_INIT )
315- return AnyType (TypeOfAny .from_error )
316-
317- # The base object has an instance type.
318-
319311 info = typ .type
320312 if override_info :
321313 info = override_info
322314
315+ method = info .get_method (name )
316+
317+ if name == "__init__" and not mx .is_super and not info .is_final :
318+ if not method or not method .is_final :
319+ # Accessing __init__ in statically typed code would compromise
320+ # type safety unless used via super() or the method/class is final.
321+ mx .fail (message_registry .CANNOT_ACCESS_INIT )
322+ return AnyType (TypeOfAny .from_error )
323+
324+ # The base object has an instance type.
325+
323326 if (
324327 state .find_occurrences
325328 and info .name == state .find_occurrences [0 ]
@@ -329,7 +332,6 @@ def analyze_instance_member_access(
329332 mx .msg .note ("Occurrence of '{}.{}'" .format (* state .find_occurrences ), mx .context )
330333
331334 # Look up the member. First look up the method dictionary.
332- method = info .get_method (name )
333335 if method and not isinstance (method , Decorator ):
334336 if mx .is_super and not mx .suppress_errors :
335337 validate_super_call (method , mx )
0 commit comments