From 8bd407c9ad790688c640f2dedee7781e8ab8c665 Mon Sep 17 00:00:00 2001 From: ashishpatel26 Date: Mon, 22 Jun 2026 23:40:54 +0530 Subject: [PATCH] spec: clarify that passthrough __new__ is ignored when converting to callable When __new__ uses only *args and **kwargs, it is a passthrough that does not constrain the constructor signature. Step 2 of the conversion algorithm should produce no callable type in this case, leaving __init__ as the sole source of the constructor's signature. The conformance test (Class3) already expected this behaviour; the spec example for class B was inconsistent. Fixes #2158. --- docs/spec/constructors.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/spec/constructors.rst b/docs/spec/constructors.rst index c95ecc488..d9b33f03d 100644 --- a/docs/spec/constructors.rst +++ b/docs/spec/constructors.rst @@ -387,7 +387,10 @@ constructor calls: 2. If the class defines a ``__new__`` method or inherits a ``__new__`` method from a base class other than ``object``, a type checker should synthesize a callable from the parameters and return type of that method after it is bound - to the class. + to the class. If the ``__new__`` method's only non-``cls`` parameters are + ``*args`` and ``**kwargs`` (i.e. a passthrough), the method is considered + to not constrain the constructor signature, and this step produces no + callable type. 3. If the return type of the method in step 2 evaluates to a type that is not a subclass of the class being constructed (or a union that includes such a @@ -454,7 +457,7 @@ constructor calls: reveal_type(accepts_callable(A)) # ``def () -> A`` - reveal_type(accepts_callable(B)) # ``def (*args, **kwargs) -> B | def (x: int) -> B`` + reveal_type(accepts_callable(B)) # ``def (x: int) -> B`` reveal_type(accepts_callable(C)) # ``def (x: int) -> int`` reveal_type(accepts_callable(D)) # ``def () -> NoReturn`` reveal_type(accepts_callable(E)) # ``def () -> A``