Re: [IDEA for RF C] let the "new" operator fail when the __construct( ) function returns a value.
| From: | Rowan Tommins [IMSoP] | Date: | Fri, 20 Feb 2026 07:40:14 +0000 |
| Subject: | Re: [IDEA for RF C] let the "new" operator fail when the __construct( ) function returns a value. | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-130101@lists.php.net to get a copy of this message | ||
On 19 February 2026 20:24:56 GMT, Mirco Babin <mirco.babin@gmail.com> wrote:
>> That's a different kind of "why". I meant, "why would a programmer
>> deliberately call a function __construct, and have no intention of
>> *ever* using it as a constructor".
>
>A theoretical example can be found in
>"Unaffected calling the parent constructor example".
>UnaffectedBaseClass could be abstract.
>
>```php
>class UnaffectedBaseClass
>{
> public function __construct()
> {
> return ['important'];
> }
>}
>
>class UnaffectedCallParentConstructor extends UnaffectedBaseClass
>{
> public function __construct()
> {
> $important = parent::__construct();
> }
>}
>
>$it = new UnaffectedCallParentConstructor();
>```
In that example, the method on UnaffectedBaseClass can not be used as a constructor under your
proposal. As such, it's just a normal method which can be trivially renamed:
```
class UnaffectedBaseClass
{
public function initialise()
{
return ['important'];
}
}
class UnaffectedCallParentConstructor extends UnaffectedBaseClass
{
public function __construct()
{
$important = parent::initialise();
}
}
$it = new UnaffectedCallParentConstructor();
```
>> If they are using it as *both* a constructor and a normal method,
>> *their code will break with your proposal* because at some point
>> they will call it as a constructor and hit the new error.
>
>Not necessarily. When an if is used, __construct() can be either.
True. I'm not convinced the language should bend over backwards to support such a pattern,
though.
>The Php scripting aspect makes it difficult in general
>for untyped projects to fail early.
This is a completely irrelevant statement. We're not talking about failing early "in
general", we're talking about a compile-time check that PHP already makes in other
contexts.
>> The only difference that delaying the error to run-time makes, is that
>> it will take longer for people to notice that it is broken.
>
>Not necessarily true. Assume the code is running fine on a shared hosting
>platform with Php 8.5. Then the hosting provider decides to force an
>update to Php 9, because of a critical vulnerability. That same code
>would then break at some point.
I don't see how this contradicts what I said. Instead of it failing immediately, it fails
"at some point" - so, it will take longer to happen. You consider that a good thing, I
consider it a bad thing; I guess we're not going to convince each other on that.
>I assume the spaghetti contains some version of my two theoretical
>examples.
>
>So it is safer to *not* make the return type declaration implicitly "void".
The way I see it, we have to draw the line somewhere regarding what use of "__construct"
methods is "acceptable", and what use we're going to force users to fix. There are
three options on the table:
1) You may return any value, the "new" operator will silently discard it [current
behaviour]
2) You must not return a value
3) You may return a value in the definition, but must make sure that no uses of the "new"
operator reach that return statement
I find option 3 unnecessarily complicated. Faced with an existing code base, checking and fixing
violations of option 2 seems a lot easier than keeping the return values but making sure they
won't error under option 3.
I think that either we should add a simple, easily checked, rule - option 2; or we should avoid
breaking people's code, and retain option 1.
Regards,
Rowan Tommins
[IMSoP]