[RFC] Default constructors

php.internals

Stas Malyshev

11 years ago
Hi! I'd like to propose the following RFC, which in short would allow any method to call parent ctor (and some other methods) even if such is not explicitly defined: https://wiki.php.net/rfc/default_ctor The reasons are outlined in detail in the RFC and here: http://php100.wordpress.com/2014/11/04/default-constructors/ The patch is not finished yet but seems to be working fine, I'll add it to the RFC this week as soon as I finish it. I'd like to put idea out there in the meantime and hear what everybody thinks about it. Thanks, Stas

Robert Stoll

11 years ago
> -----Ursprüngliche Nachricht----- > Von: Stanislav Malyshev [mailto:smalyshev@gmail.com] > Gesendet: Dienstag, 18. November 2014 10:21 > An: PHP Internals > Betreff: [PHP-DEV] [RFC] Default constructors > > Hi! > > I'd like to propose the following RFC, which in short would allow any method to call parent ctor (and some other methods) > even if such is not explicitly defined: > > https://wiki.php.net/rfc/default_ctor > > The reasons are outlined in detail in the RFC and here: > http://php100.wordpress.com/2014/11/04/default-constructors/ > > The patch is not finished yet but seems to be working fine, I'll add it to the RFC this week as soon as I finish it. I'd like to put > idea out there in the meantime and hear what everybody thinks about it. > > Thanks, > Stas > > -- > PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
+1 And concerning the subtle BC break, I think it is a bug that bar is currently not executed. In other cases where superfluous arguments are provided, they are evaluated. Hence, inconsistent anyway and should be fixed IMO. Another example which outlines that the new behaviour is more appropriate: class Foo{} $b = 0; //left over from refactoring, $b is currently not incremented even though it looks like that, new behaviour would fix that $a = new Foo(++$b);

Ferenc Kovacs

11 years ago
On Tue, Nov 18, 2014 at 10:20 AM, Stanislav Malyshev <smalyshev@gmail.com> wrote:
> Hi! > > I'd like to propose the following RFC, which in short would allow any > method to call parent ctor (and some other methods) even if such is not > explicitly defined: > > https://wiki.php.net/rfc/default_ctor > > The reasons are outlined in detail in the RFC and here: > http://php100.wordpress.com/2014/11/04/default-constructors/ > > The patch is not finished yet but seems to be working fine, I'll add it > to the RFC this week as soon as I finish it. I'd like to put idea out > there in the meantime and hear what everybody thinks about it. > > Thanks, > Stas > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
Hi Stas, Thanks for bringing this up and working on the patch. Last time we discussed this( http://www.serverphorums.com/read.php?7,712222,712635), there were a couple of people including Anthony and Sanford who were agains this feature arguing that it would encourage bad practices so I think it would be useful to look at those concerns if they (still) have merit.
-- Ferenc Kovács @Tyr43l - http://tyrael.hu

Stas Malyshev

11 years ago
Hi!
> Thanks for bringing this up and working on the patch. > Last time we discussed > this(http://www.serverphorums.com/read.php?7,712222,712635), there were > a couple of people including Anthony and Sanford who were agains this > feature arguing that it would encourage bad practices so I think it
Obviously, I disagree with that. I do not see any bad practices it encourages - if anything, it encourages the good practice of always calling parent ctor, practice considered so good by many that some languages make it mandatory. The discussion of __call etc. presented there does not seem too relevant for me - __call was never called on missing ctor and it makes zero sense to do so since no sane implementation uses __call do dispatch constructors. I'll need to check though if my changes don't have BC impact on __call (they should not, but I did not check before, so I'll check that too). Thanks, Stas

Andrew Faulds

11 years ago
> On 18 Nov 2014, at 19:00, Stanislav Malyshev <smalyshev@gmail.com> wrote: > >> Thanks for bringing this up and working on the patch. >> Last time we discussed >> this(http://www.serverphorums.com/read.php?7,712222,712635), there were >> a couple of people including Anthony and Sanford who were agains this >> feature arguing that it would encourage bad practices so I think it > > Obviously, I disagree with that. I do not see any bad practices it > encourages - if anything, it encourages the good practice of always > calling parent ctor, practice considered so good by many that some > languages make it mandatory.
Yes, calling the parent constructor is good practice. That doesn’t mean we should add this, though. Because this RFC means you can just blindly call the constructor, whether or not it exists, and expect it to work. And that is bad: If you don’t know how the parent class works, you really shouldn’t be extending it.
-- Andrea Faulds http://ajf.me/

Stas Malyshev

11 years ago
Hi!
> mean we should add this, though. Because this RFC means you can just > blindly call the constructor, whether or not it exists, and expect it
Yes, that's exactly what it means and it's good, not bad - new() has been doing that for years and nobody complained.
> to work. And that is bad: If you don’t know how the parent class > works, you really shouldn’t be extending it. -- Andrea Faulds
That sounds just wrong - information hiding is a basic premise of OO, and to extend the object you shouldn't have to know the intimate details of its implementation. In fact, in many cases you can't - such as with internal classes. That's why we have problems with class initilization for extending internal classes - because people are trained "you can't just call the parent ctor, you need to verify things thoroughly first". And that'd exactly wrong. If you know you can create an object without parameters - new Foo() - then you should be able to extend it and call parent::__construct() - which is supposed to do exactly the same. Unfortunately, in PHP - unlike pretty much any other OO language - you can not.

Alexander Kurilo

11 years ago
On 18/11/14 14:00, Stanislav Malyshev wrote:
> Hi! > >> Thanks for bringing this up and working on the patch. >> Last time we discussed >> this(http://www.serverphorums.com/read.php?7,712222,712635), there were >> a couple of people including Anthony and Sanford who were agains this >> feature arguing that it would encourage bad practices so I think it > > Obviously, I disagree with that. I do not see any bad practices it > encourages - if anything, it encourages the good practice of always > calling parent ctor, practice considered so good by many that some > languages make it mandatory.
However, Java lets one have as many constructors as one wants because Java supports overloading and there's a default constructor that takes no arguments. Does it *really* make sense for PHP? What if that parent class 'Animal' from your example introduces a constructor that accepts, say, both `$owner` and `$what` as mandatory arguments? `parent::__construct()` call in a descendant will appear broken (unintentionally, I suppose), won't it? That'll work in Java just fine, though.

Stas Malyshev

11 years ago
Hi!
> Does it *really* make sense for PHP? What if that parent class 'Animal' > from your example introduces a constructor that accepts, say, both > `$owner` and `$what` as mandatory arguments? `parent::__construct()`
Then you need to rewrite all descendant classes anyway, this would be API change, not an API-preserving refactoring. Essentially, you take the Animal class and replace it with entirely different class with different requirements. You'll have to rewrite all the code that constructs Animal objects. This obviously is not the scenario I'm talking about (and of course nowhere near recommended practice for any maintainable code).
> call in a descendant will appear broken (unintentionally, I suppose), > won't it? That'll work in Java just fine, though.
In Java, you can not do that - if your ctor requires 2 arguments, you'd have to give it 2 arguments. If you still have the default ctor, that'd be fine, and so it will be in PHP - but in PHP you can not have two ctor functions, so in PHP you do things differently, we use optional arguments instead of using two functions. The meaning is the same though - if you're able to call new Foo(), you should be able to call parent::__construct() (or super() in Java case) on Foo. Except in Java it works and in PHP it doesn't. That's what I want to fix.

Rowan Collins

11 years ago
On 18/11/2014 20:20, Alexander Kurilo wrote:
> Does it *really* make sense for PHP? What if that parent class > 'Animal' from your example introduces a constructor that accepts, say, > both `$owner` and `$what` as mandatory arguments? > `parent::__construct()` call in a descendant will appear broken > (unintentionally, I suppose), won't it?
If you introduce a mandatory parameter to *any* function, method, or constructor, existing calls to that function, method, or constructor will be broken. A class with no defined constructor already behaves as if its constructor had no arguments when using "new", so introducing a constructor with mandatory arguments is already a breaking change.
-- Rowan Collins [IMSoP]

Derick Rethans

11 years ago
On Tue, 18 Nov 2014, Stanislav Malyshev wrote:
> Hi! > > I'd like to propose the following RFC, which in short would allow any > method to call parent ctor (and some other methods) even if such is not > explicitly defined: > > https://wiki.php.net/rfc/default_ctor > > The reasons are outlined in detail in the RFC and here: > http://php100.wordpress.com/2014/11/04/default-constructors/ > > The patch is not finished yet but seems to be working fine, I'll add it > to the RFC this week as soon as I finish it. I'd like to put idea out > there in the meantime and hear what everybody thinks about it.
You write:
> Also, this can lead to more subtle BC breaks. Consider this code:
And then further on:
> No backward incompatible changes, sin...
that can not be both right. cheers, Derick

Stas Malyshev

11 years ago
Hi!
> You write: > >> Also, this can lead to more subtle BC breaks. Consider this code: > > And then further on: > >> No backward incompatible changes, sin... > > that can not be both right.
Ah, but the former describes the option that has been *rejected*. The option that was chosen instead does not have the BC break.

Rowan Collins

11 years ago
On 18/11/2014 18:54, Stanislav Malyshev wrote:
> Hi! > >> You write: >> >>> Also, this can lead to more subtle BC breaks. Consider this code: >> And then further on: >> >>> No backward incompatible changes, sin... >> that can not be both right. > Ah, but the former describes the option that has been *rejected*. The > option that was chosen instead does not have the BC break. >
Personally, I would much prefer the backwards compatibility break to happen. It is frankly quite bizarre, and not at all useful, that the following two pieces of code behave differently: class Foo {} new Foo( print('hello') ); // silent vs class Foo { function __construct() {} } new Foo( print('hello') ); // says "hello" (Incidentally, HHVM doesn't have this "optimisation", and says "hello" in both cases: http://3v4l.org/ZDXs1) If I came upon this without knowing more, I would assume it was a bug in PHP, and any code relying on it was in need of fixing ASAP. Regards,
-- Rowan Collins [IMSoP]

Andrew Faulds

11 years ago
> On 18 Nov 2014, at 21:51, Rowan Collins <rowan.collins@gmail.com> wrote: > > Personally, I would much prefer the backwards compatibility break to happen. It is frankly quite bizarre, and not at all useful, that the following two pieces of code behave differently: > > class Foo {} > new Foo( print('hello') ); > // silent > > vs > > class Foo { function __construct() {} } > new Foo( print('hello') ); > // says "hello" > > (Incidentally, HHVM doesn't have this "optimisation", and says "hello" in both cases: http://3v4l.org/ZDXs1) > > If I came upon this without knowing more, I would assume it was a bug in PHP, and any code relying on it was in need of fixing ASAP.
In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829
-- Andrea Faulds http://ajf.me/

Stas Malyshev

11 years ago
Hi!
> In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829
It is most definitely not a bug, it's the intended behavior that has been coded so and has been in PHP for a very long time. You may argue it should not be so, and it should be changed, that's fine, but it's not what is called a bug - it's not a mistake, it's how it was intended to work. Changing this is a feature request, for which you're welcome to make an RFC. I'm not sure though it would be very useful change since IMO it would break BC for no actual gain to any practical code. But if you think you're wrong RFC is definitely an option.

Andrew Faulds

11 years ago
> On 18 Nov 2014, at 22:54, Stanislav Malyshev <smalyshev@gmail.com> wrote: > > Hi! > >> In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829 > > It is most definitely not a bug, it's the intended behavior that has > been coded so and has been in PHP for a very long time. You may argue it > should not be so, and it should be changed, that's fine, but it's not > what is called a bug - it's not a mistake, it's how it was intended to > work.
Are you sure it was intended to work this way, with the parameters not being evaluated at all? Is that actually useful in any context? Function calls always evaluate their arguments, do they not? PHP is a language with functions that have side effects.
> Changing this is a feature request, for which you're welcome to > make an RFC. I'm not sure though it would be very useful change since > IMO it would break BC for no actual gain to any practical code. But if > you think you're wrong RFC is definitely an option.
Alright then, it’s a “feature” that needs fixing, not a bug.
-- Andrea Faulds http://ajf.me/

Stas Malyshev

11 years ago
Hi!
> Are you sure it was intended to work this way, with the parameters > not being evaluated at all?
Of course, just look at how ZEND_NEW opcode is written. It's the only reason in has op2 there. That code is not a typo, it's intended to skip the function call.
> Is that actually useful in any context? Function calls always evaluate
their arguments, do they not? PHP is a language with functions that have side effects. That's why, again, ZEND_NEW opcode has op2 - if ctor is not defined, it does not initiate the function call. It'd be hard to initiate it since there's no actual function there, but of course with some work and additional branches in the code that executes functions it probably can be done.
> Alright then, it’s a “feature” that needs fixing, not a bug.
Sure, you are as welcome to write RFC and a patch as anybody else :) So far it's been there for about 10 years and nobody did, but that should not be a problem. More problem would be to actually make the engine to be able to initiate the function call (and handle all the stack frames, make backtraces/exceptions work, etc.) without actually having any function there but I'm sure this is possible. Actually, the patch for default ctors that I'm finishing may give you some tools to do this. I personally am not completely sure it's worth the trouble - since, again, no sane code should ever rely on something like this - but maybe I'm wrong that there's a valid use case for this.

Rowan Collins

11 years ago
On 18/11/2014 23:07, Stanislav Malyshev wrote:
> Hi! > >> Are you sure it was intended to work this way, with the parameters >> not being evaluated at all? > Of course, just look at how ZEND_NEW opcode is written. It's the only > reason in has op2 there. That code is not a typo, it's intended to skip > the function call.
I don't know the innards of the engine well enough to follow this, but it sounds like you're talking about skipping the evaluation of __construct() as a method if it doesn't exist as one, which is perfectly reasonable. However, the side effect that the *arguments* to that function call are not executed is surely an unintended side-effect of this, which was considered not important enough to worry about.
> I personally am not completely sure it's worth the trouble - since, > again, no sane code should ever rely on something like this - but maybe > I'm wrong that there's a valid use case for this.
Sorry, I'm not sure what you are referring to by "this" here. To quote an earlier example: $b = 0; $a = new Foo(++$b); Looks like pretty normal code to me; no reason to expect anything about the way class Foo is defined to affect its behaviour. No sane code should rely on that *not* incrementing $b, surely?
-- Rowan Collins [IMSoP]

Rowan Collins

11 years ago
On 18/11/2014 22:54, Stanislav Malyshev wrote:
> It is most definitely not a bug, it's the intended behavior that has > been coded so and has been in PHP for a very long time. You may argue it > should not be so, and it should be changed, that's fine, but it's not > what is called a bug - it's not a mistake, it's how it was intended to > work.
"Been in PHP for a very long time" != "how it was intended to work". Can you explain why this would be the intention of anyone designing the language? It seems to me that it is an unforeseen side effect of a different feature - that when raising a Fatal Error for a non-existent function or method, the runtime bails out immediately, without bothering to evaluate the arguments. That's very different from a non-existent constructor call *successfully executing* without its parameters being evaluated. It's a mistake that was made a long time ago, and nobody's thought it worth the effort to fix, but it's still a mistake, IMHO.
-- Rowan Collins [IMSoP]

Stas Malyshev

11 years ago
Hi!
> "Been in PHP for a very long time" != "how it was intended to work". Can > you explain why this would be the intention of anyone designing the > language?
Of course, been for a long time is not the same as intended. But if you look at how ZEND_NEW is done, it's clear it's intended. And the reason is simple - if there's no function, it's not really possible to initiate a function call and handle it properly, since the engine expects certain data there and there's nothing to provide that data. So, ZEND_NEW having no function just skips the whole function call thing altogether.
> It's a mistake that was made a long time ago, and nobody's thought it > worth the effort to fix, but it's still a mistake, IMHO.
It's not a mistake - at least, not an unintentional one, it was a decision. If you think the decision was wrong and it can be done better - cool, let's see the patch.

Rowan Collins

11 years ago
On 18/11/2014 23:11, Stanislav Malyshev wrote:
>> "Been in PHP for a very long time" != "how it was intended to work". Can >> >you explain why this would be the intention of anyone designing the >> >language? > Of course, been for a long time is not the same as intended. But if you > look at how ZEND_NEW is done, it's clear it's intended. And the reason > is simple - if there's no function, it's not really possible to initiate > a function call and handle it properly, since the engine expects certain > data there and there's nothing to provide that data. So, ZEND_NEW having > no function just skips the whole function call thing altogether. >
This is where I struggle: to me, the "++$b" in "foo(++$b)" or "new Foo(++$b)" isn't part of the function call; it's a statement that has to be evaluated *before* the function call can happen. If a fatal error is being raised, it makes (some) sense to skip that evaluation, but if execution is continuing, it seems perfectly natural for that expression to be evaluated even if its result is discarded.
> If you think the decision was wrong and it can be done better > - cool, let's see the patch.
I'm happy to accept that this is a low-priority, hard-to-fix, bug. I just don't see that it can be justified as a feature.
-- Rowan Collins [IMSoP]

Rowan Collins

11 years ago
On 18/11/2014 23:20, Rowan Collins wrote:
> If a fatal error is being raised, it makes (some) sense to skip that > evaluation
To be honest, it's a little weird to me that these two programs behave differently: $a = print('hello'); non_existent_function($a); vs non_existent_function( print('hello') ); But relying on the exact behaviour during a fatal error would certainly be ill-advised.
-- Rowan Collins [IMSoP]

Stas Malyshev

11 years ago
Hi!
> I'm happy to accept that this is a low-priority, hard-to-fix, bug. I > just don't see that it can be justified as a feature.
We can argue semantics of the word "bug" all day long, but the fact is the functionality as it is is there by an explicit decision - it was chosen to be this way and no other way, for the reasons I have described, it was no omission and no unintended side-effect of something, it was meant to work this way. If you want to call it "hard to fix bug" knowing this, you're welcome to.

Rowan Collins

11 years ago
On 18/11/2014 21:53, Andrea Faulds wrote:
>> On 18 Nov 2014, at 21:51, Rowan Collins <rowan.collins@gmail.com> wrote: >> >> Personally, I would much prefer the backwards compatibility break to happen. It is frankly quite bizarre, and not at all useful, that the following two pieces of code behave differently: >> >> class Foo {} >> new Foo( print('hello') ); >> // silent >> >> vs >> >> class Foo { function __construct() {} } >> new Foo( print('hello') ); >> // says "hello" >> >> (Incidentally, HHVM doesn't have this "optimisation", and says "hello" in both cases: http://3v4l.org/ZDXs1) >> >> If I came upon this without knowing more, I would assume it was a bug in PHP, and any code relying on it was in need of fixing ASAP. > In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829
Or, depending on who looks at the report, it's Not A Bug: https://bugs.php.net/bug.php?id=54162 But, yes, I would argue that both reports are actually valid, and this behaviour, however long-standing, is an accident of implementation, not a design decision that anyone can actually justfiy. Regards,
-- Rowan Collins [IMSoP]

Ivan Enderlin @ Hoa

11 years ago
Hello :-), Is it not simpler to create a super-object whom all objects are children of? Something similar to the Java `Object`? Cheers :-). Le 18/11/2014 10:20, Stanislav Malyshev a écrit :
> Hi! > > I'd like to propose the following RFC, which in short would allow any > method to call parent ctor (and some other methods) even if such is not > explicitly defined: > > https://wiki.php.net/rfc/default_ctor > > The reasons are outlined in detail in the RFC and here: > http://php100.wordpress.com/2014/11/04/default-constructors/ > > The patch is not finished yet but seems to be working fine, I'll add it > to the RFC this week as soon as I finish it. I'd like to put idea out > there in the meantime and hear what everybody thinks about it. > > Thanks, > Stas >
-- Ivan Enderlin Developer of Hoa http://hoa-project.net/ PhD. at DISC/Femto-ST (Vesontio) and INRIA (Cassis) http://disc.univ-fcomte.fr/ and http://www.inria.fr/ Member of HTML and WebApps Working Group of W3C http://w3.org/

Ferenc Kovacs

11 years ago
On Tue, Nov 18, 2014 at 1:35 PM, Ivan Enderlin @ Hoa < ivan.enderlin@hoa-project.net> wrote:
> Hello :-), > > Is it not simpler to create a super-object whom all objects are children > of? Something similar to the Java `Object`? > >
yeah, this was also a suggested alternative when discussing this problem previously(see the link in my previous mail).
-- Ferenc Kovács @Tyr43l - http://tyrael.hu

Andrew Faulds

11 years ago
> On 18 Nov 2014, at 12:47, Ferenc Kovacs <tyra3l@gmail.com> wrote: > > On Tue, Nov 18, 2014 at 1:35 PM, Ivan Enderlin @ Hoa < > ivan.enderlin@hoa-project.net> wrote: > >> Hello :-), >> >> Is it not simpler to create a super-object whom all objects are children >> of? Something similar to the Java `Object`? > yeah, this was also a suggested alternative when discussing this problem > previously(see the link in my previous mail).
I'd certainly like it if everything descended from some class (Object? StdClass?), but I don't like the idea of an empty construct. As Anthony pointed out last time, you can't do inheritance and simultaneously treat the parent class as a black box.
-- Andrea Faulds http://ajf.me/

Rowan Collins

11 years ago
Andrea Faulds wrote on 18/11/2014 13:11:
>> On 18 Nov 2014, at 12:47, Ferenc Kovacs <tyra3l@gmail.com> wrote: >> >> On Tue, Nov 18, 2014 at 1:35 PM, Ivan Enderlin @ Hoa < >> ivan.enderlin@hoa-project.net> wrote: >> >>> Hello :-), >>> >>> Is it not simpler to create a super-object whom all objects are children >>> of? Something similar to the Java `Object`? >> yeah, this was also a suggested alternative when discussing this problem >> previously(see the link in my previous mail). > I'd certainly like it if everything descended from some class (Object? StdClass?), but I don't like the idea of an empty construct. As Anthony pointed out last time, you can't do inheritance and simultaneously treat the parent class as a black box.
The thing is that without any way of monkey-patching the default object, there isn't much difference between "all objects have a default constructor" and "all objects have a default parent", other than "$foo instanceOf Object" always returning true. Regards,
-- Rowan Collins [IMSoP]

Stas Malyshev

11 years ago
Hi!
>> I'd certainly like it if everything descended from some class (Object? >> StdClass?), but I don't like the idea of an empty construct. As
Making everything descend from the same class may require a number of changes and much bigger design effort than this RFC aims at, with wider BC implications. As for not liking the idea of empty construct - that's too bad since PHP already has it and had it since forever. You just can't call it with parent:: syntax - but you perfectly can use it (not sure you can say "call" since no call is actually happening) with new.
>> Anthony pointed out last time, you can't do inheritance and >> simultaneously treat the parent class as a black box.
I'm not sure what is meant here. Calling parent ctor is a base OOP technique, everybody does that, it's one of the first best practices people learn when doing OO. Only in PHP, it's weird since you have to know if parent defined ctor or not, and if that changes, patch all your descendant classes. That's just bad OO implementation.

Markus Fasselt

11 years ago
Hi!
> Making everything descend from the same class may require a number of > changes and much bigger design effort than this RFC aims at, with wider > BC implications.
I am not sure, whether this might be a problem (I am just starting to dive into PHP internals), but I can think of constructor visibility problems. What visibility should the main constructor have? If it is public (or protected), you can't have private constructors anylonger
> Fatal error: Access level to Foo::__construct() must be public (as in
class BaseClass) So there have to be changes in the validation of a class and in the instantiation to not get this problem. Don't know whether this is a bigger concern, but I just got this idea.

Alexander Lissachenko

11 years ago
Hi! 2014-11-18 12:20 GMT+03:00 Stanislav Malyshev <smalyshev@gmail.com>:
> > I'd like to propose the following RFC, which in short would allow any > method to call parent ctor (and some other methods) even if such is not > explicitly defined:
+1 for defining base class for all classes and addition of default constructor implementation in it. One more example with inconsistent ctors handling via Reflection: http://3v4l.org/Tjn82

Dmitry Stogov

11 years ago
Hi Stas, Sorry, I didn't follow all the discussions. I think the idea is good. I'm not sure about implementation. Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive. I think it must be better to use special predefined function (see "zend_pass_function" usage in zend_vm_def.h). Thanks. Dmitry. On Tue, Nov 18, 2014 at 12:20 PM, Stanislav Malyshev <smalyshev@gmail.com> wrote:

Stas Malyshev

11 years ago
Hi!
> I think the idea is good. > I'm not sure about implementation. > Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive. > I think it must be better to use special predefined function (see > "zend_pass_function" usage in zend_vm_def.h).
I've moved the condition after internal & user function, so the slowdown would almost never happen and will be very minimal. But if you prefer, I can do the other one, I actually implemented it first with the function but then removed it since I thought ability to skip a function call may be faster and also prove useful in other cases. I'll try to do another version with zend_pass_function and see if I see any difference.
-- Stas Malyshev smalyshev@gmail.com

Stas Malyshev

11 years ago
Hi!
>> Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive. >> I think it must be better to use special predefined function (see >> "zend_pass_function" usage in zend_vm_def.h).
I've made a different implementation here: https://github.com/smalyshev/php-src/compare/php:master...smalyshev:default_ctor_func?expand=1 which uses zend_pass_function but I had to make it static since otherwise it's increase refcount for object and it doesn't seem like it decrements back. So I'm not sure if it's right, what do you think?
-- Stas Malyshev smalyshev@gmail.com

Dmitry Stogov

11 years ago
thanks Stas. I'll think on next week. Dmitry. On Fri, Nov 21, 2014 at 6:59 AM, Stanislav Malyshev <smalyshev@gmail.com> wrote:

Dmitry Stogov

11 years ago
I like the last patch. I think ZEND_ACC_STATIC flag must not make any problems. However, I thought about one more inconsistent. Your patch works fine for "parent::" methods but not for "grandparents::" In the following code "default constructor" won't work. class A { } class B extends A { } class C extends B { function __constructor() { A::_constructor(); // this won't work } } It's not a big problem to fix implementation to support it, or may be support for "parent::" is enough. Anyway, it should be reflected in RFC (if this code should work or should not). Thanks. Dmitry. On Fri, Nov 21, 2014 at 10:40 AM, Dmitry Stogov <dmitry@zend.com> wrote:

Rowan Collins

11 years ago
Dmitry Stogov wrote on 24/11/2014 09:56:
> However, I thought about one more inconsistent. Your patch works fine for > "parent::" methods but not for "grandparents::" > In the following code "default constructor" won't work. > > class A { > } > class B extends A { > } > class C extends B { > function __constructor() { > A::_constructor(); // this won't work > } > }
I guess some inconsistency like this is hard to avoid unless the default constructor is actually added to the class's method table, because the code has to specifically check for each case that is to be supported. At risk of flogging a dead horse, this is why I was arguing for the lazy evaluation with new keyword to be abandoned, because it seems like that's the primary compatibility issue with adding a "real" default definition. Reflection would show the method as either "internal" or inherited from some implicit base class. From a user's point of view there should really be no difference between "no constructor" and "constructor which does nothing", IMHO. Regards,
-- Rowan Collins [IMSoP]

Stas Malyshev

11 years ago
Hi!
> However, I thought about one more inconsistent. Your patch works fine > for "parent::" methods but not for "grandparents::" > In the following code "default constructor" won't work.
Yes, this is OK - the support is only for one pattern, calling the parent, because it's what you're supposed to do. If you do anything else, it would work (or not work) as before since it's not the best practice so you're on your own.
> It's not a big problem to fix implementation to support it, or may be > support for "parent::" is enough. > Anyway, it should be reflected in RFC (if this code should work or > should not).
Sure, I'll add a note on RFC about it.
-- Stas Malyshev smalyshev@gmail.com