@@ -190,7 +190,10 @@ def visit_func_def(self, o: FuncDef) -> None:
190190 self .add_dependency (trigger , target = make_trigger (target ))
191191 if o .info :
192192 for base in non_trivial_bases (o .info ):
193- self .add_dependency (make_trigger (base .fullname () + '.' + o .name ()))
193+ # Base class __init__/__new__ doesn't generate a logical
194+ # dependency since the override can be incompatible.
195+ if not self .use_logical_deps () or o .name () not in ('__init__' , '__new__' ):
196+ self .add_dependency (make_trigger (base .fullname () + '.' + o .name ()))
194197 self .add_type_alias_deps (self .scope .current_target ())
195198 super ().visit_func_def (o )
196199 variants = set (o .expanded ) - {o }
@@ -295,24 +298,32 @@ def process_type_info(self, info: TypeInfo) -> None:
295298 # doesn't affect precision of Liskov checking.
296299 if name not in info .names :
297300 continue
301+ # __init__ and __new__ can be overridden with different signatures, so no
302+ # logical depedency.
303+ if name in ('__init__' , '__new__' ):
304+ continue
298305 self .add_dependency (make_trigger (base_info .fullname () + '.' + name ),
299306 target = make_trigger (info .fullname () + '.' + name ))
300- self .add_dependency (make_trigger (base_info .fullname () + '.__init__' ),
301- target = make_trigger (info .fullname () + '.__init__' ))
302- self .add_dependency (make_trigger (base_info .fullname () + '.__new__' ),
303- target = make_trigger (info .fullname () + '.__new__' ))
304- # If the set of abstract attributes change, this may invalidate class
305- # instantiation, or change the generated error message, since Python checks
306- # class abstract status when creating an instance.
307- #
308- # TODO: We should probably add this dependency only from the __init__ of the
309- # current class, and independent of bases (to trigger changes in message
310- # wording, as errors may enumerate all abstract attributes).
311- self .add_dependency (make_trigger (base_info .fullname () + '.(abstract)' ),
312- target = make_trigger (info .fullname () + '.__init__' ))
313- # If the base class abstract attributes change, subclass abstract
314- # attributes need to be recalculated.
315- self .add_dependency (make_trigger (base_info .fullname () + '.(abstract)' ))
307+ if not self .use_logical_deps ():
308+ # These dependencies are only useful for propagating changes --
309+ # they aren't logical dependencies since __init__ and __new__ can be
310+ # overridden with a different signature.
311+ self .add_dependency (make_trigger (base_info .fullname () + '.__init__' ),
312+ target = make_trigger (info .fullname () + '.__init__' ))
313+ self .add_dependency (make_trigger (base_info .fullname () + '.__new__' ),
314+ target = make_trigger (info .fullname () + '.__new__' ))
315+ # If the set of abstract attributes change, this may invalidate class
316+ # instantiation, or change the generated error message, since Python checks
317+ # class abstract status when creating an instance.
318+ #
319+ # TODO: We should probably add this dependency only from the __init__ of the
320+ # current class, and independent of bases (to trigger changes in message
321+ # wording, as errors may enumerate all abstract attributes).
322+ self .add_dependency (make_trigger (base_info .fullname () + '.(abstract)' ),
323+ target = make_trigger (info .fullname () + '.__init__' ))
324+ # If the base class abstract attributes change, subclass abstract
325+ # attributes need to be recalculated.
326+ self .add_dependency (make_trigger (base_info .fullname () + '.(abstract)' ))
316327
317328 def visit_import (self , o : Import ) -> None :
318329 for id , as_id in o .ids :
0 commit comments