[RFC][Vote] Typed Properties

php.internals

Joe Watkins

10 years ago
Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe

Larry Garfield

10 years ago
On 05/20/2016 08:05 AM, Joe Watkins wrote:
> Morning internals, > > Since we have our answer on nullable types, typed properties can now go > to vote. > > https://wiki.php.net/rfc/typed-properties#vote > > Note that, support for nullability as RFC'd will be merged when the > implementation for nullable_types is merged into master. > > Please participate. > > Cheers > Joe
I don't get a vote, but I will say "endorse!" --Larry Garfield

Lester Caine

10 years ago
On 20/05/16 07:05, Joe Watkins wrote:
> Morning internals, > > Since we have our answer on nullable types, typed properties can now go > to vote. > > https://wiki.php.net/rfc/typed-properties#vote > > Note that, support for nullability as RFC'd will be merged when the > implementation for nullable_types is merged into master.
I have just realised exactly why I have a problem with most of this ... Domain! Used as an 'OtherThing' This is ALSO attributes, since an SQL domain defines all of the attributes that I need to handle in relation to variables. 'int' on it's own does very little since one still needs to add all the other checks, but adding 'types' as a properly formatted domain solves all the problems I'm looking at ... and leaves plenty of room for others to abuse the in their own way? http://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-ddl-domn.html Note such elements as [<array_dim>] to allow for arrays of a datatype although that still leaves the handling of mix arrays. Some of the conditions may seem irreverent, but if the domain is a set of keys for an array that logic then makes sense? I can even see the addition of a 'read only' flag to solve that problem while still constraining the initial setting of a domain. But this is simply user land code and does not need a small subset of elements of it added to the code base?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Guilherme Blanco

10 years ago
Joe, I fixed a minor typo in the RFC, hope you didn't mind. =) On Fri, May 20, 2016 at 5:25 AM, Lester Caine <lester@lsces.co.uk> wrote:
> On 20/05/16 07:05, Joe Watkins wrote: > > Morning internals, > > > > Since we have our answer on nullable types, typed properties can now > go > > to vote. > > > > https://wiki.php.net/rfc/typed-properties#vote > > > > Note that, support for nullability as RFC'd will be merged when the > > implementation for nullable_types is merged into master. > > I have just realised exactly why I have a problem with most of this ... > Domain! Used as an 'OtherThing' > > This is ALSO attributes, since an SQL domain defines all of the > attributes that I need to handle in relation to variables. 'int' on it's > own does very little since one still needs to add all the other checks, > but adding 'types' as a properly formatted domain solves all the > problems I'm looking at ... and leaves plenty of room for others to > abuse the in their own way? > > > http://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-ddl-domn.html > > Note such elements as [<array_dim>] to allow for arrays of a datatype > although that still leaves the handling of mix arrays. > > Some of the conditions may seem irreverent, but if the domain is a set > of keys for an array that logic then makes sense? > > I can even see the addition of a 'read only' flag to solve that problem > while still constraining the initial setting of a domain. > > But this is simply user land code and does not need a small subset of > elements of it added to the code base? > > -- > Lester Caine - G8HFL > ----------------------------- > Contact - http://lsces.co.uk/wiki/?page=contact > L.S.Caine Electronic Services - http://lsces.co.uk > EnquirySolve - http://enquirysolve.com/ > Model Engineers Digital Workshop - http://medw.co.uk > Rainbow Digital Media - http://rainbowdigitalmedia.co.uk > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Guilherme Blanco Lead Architect at E-Block

Tom Worster

10 years ago
On 5/20/16 2:05 AM, Joe Watkins wrote:
> Morning internals, > > Since we have our answer on nullable types, typed properties can now go > to vote. > > https://wiki.php.net/rfc/typed-properties#vote > > Note that, support for nullability as RFC'd will be merged when the > implementation for nullable_types is merged into master. > > Please participate.
I lack suffrage but I have a question about coercion and strictness. When I assign a value to a property declared with scalar type, is it the strictness of the file containing the assignment that controls if coercion happens or not? And is the strictness of the file containing the declaration irrelevant? I guess yes on both to be consistent with coercion on function invocation but I couldn't find this mentioned in the RFC. Tom

Joe Watkins

10 years ago
Morning Tom,
> I guess yes on both to be consistent with coercion on function invocation
but I couldn't find this mentioned in the RFC. Correct. I only made brief mention that the rules for coercion and strictness are reused. Cheers Joe On Fri, May 20, 2016 at 6:59 PM, Tom Worster <fsb@thefsb.org> wrote:

Dmitry Stogov

10 years ago
The patch "corrupts" opcache shared memory. PHP crashes with opcache.protect_memory=1. $ USE_ZEND_ALLOC=0 valgrind sapi/cli/php -d opcache.protect_memory=1 ../Zend/tests/type_declarations/typed_properties_027.php ==900== Memcheck, a memory error detector ==900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==900== Command: sapi/cli/php ../Zend/tests/type_declarations/typed_properties_027.php ==900== ==900== ==900== Process terminating with default action of signal 11 (SIGSEGV) ==900== Bad permissions for mapped region at address 0xF00FFBC8 ==900== at 0x86391FE: zend_verify_weak_scalar_type_hint (zend_execute.c:725) ==900== by 0x8639833: zend_verify_scalar_property_type (zend_execute.c:869) ==900== by 0x8639C2B: zend_verify_property_type (zend_execute.c:938) ==900== by 0x862E46D: zend_std_write_property (zend_object_handlers.c:753) ==900== by 0x8685102: ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER (zend_vm_execute.h:42160) ==900== by 0x863F91D: execute_ex (zend_vm_execute.h:426) ==900== by 0x863F9D2: zend_execute (zend_vm_execute.h:471) ==900== by 0x85F38B4: zend_execute_scripts (zend.c:1427) ==900== by 0x85832B7: php_execute_script (main.c:2492) ==900== by 0x86AE2D8: do_cli (php_cli.c:982) ==900== by 0x86AEF42: main (php_cli.c:1352) ==900== ________________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe

Dmitry Stogov

10 years ago
Hi Joe, The performance effect of this implementation is terrible. Assignment to typed property is 2.3 times slower. Assignment to untyped property in a class with typed properties is 1.8 times slower. See the benchmark https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 Thanks. Dmitry. ________________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe

Dmitry Stogov

10 years ago
I appreciate the work done by Joe, but I vote "no", because the implementation is not good enough yet - it's incompatible with opcache (may be it's not a big problem to fix this) - typed properties assignment is going to be 2-3 times slower ($obj->x += 2; is 3 times slower) - the patch makes slight negative effect even for untyped properties - the proposed behavior for uninitialized typed properties assumes that they have to be checked on each "read". This checks will have to be performed even in native JITed code. I don't see a reason for typing if we have to perform check on each read anyway. Thanks. Dmitry. ________________________________________ From: Dmitry Stogov <dmitry@zend.com> Sent: Monday, May 23, 2016 11:30:09 AM To: Joe Watkins; PHP internals; Phil Sturgeon Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties Hi Joe, The performance effect of this implementation is terrible. Assignment to typed property is 2.3 times slower. Assignment to untyped property in a class with typed properties is 1.8 times slower. See the benchmark https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 Thanks. Dmitry. ________________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php

Ivan Enderlin @ Hoa

10 years ago
I vote no for the same performance reason, but the whole Hoa's community is agree with the RFC. Thanks for the hard work! On 23/05/16 11:02, Dmitry Stogov wrote:

Stas Malyshev

10 years ago
Hi!
> The performance effect of this implementation is terrible. > > Assignment to typed property is 2.3 times slower. > Assignment to untyped property in a class with typed properties is 1.8 times slower. > > See the benchmark > https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800
This is not good. I wonder why these tests weren't made before the vote and results wheren't added in the RFC. Should we make it a standard practice to do so? Having 2x slowdown on each property access sounds like a bad idea.
-- Stas Malyshev smalyshev@gmail.com

Julien Pauli

10 years ago
On Mon, May 23, 2016 at 11:09 AM, Stanislav Malyshev <smalyshev@gmail.com> wrote:
> Hi! > >> The performance effect of this implementation is terrible. >> >> Assignment to typed property is 2.3 times slower. >> Assignment to untyped property in a class with typed properties is 1.8 times slower. >> >> See the benchmark >> https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 > > This is not good. I wonder why these tests weren't made before the vote > and results wheren't added in the RFC. Should we make it a standard > practice to do so? Having 2x slowdown on each property access sounds > like a bad idea.
The question is : * should the vote be an idea-based vote, or integrate the code into the vote ? My vote did not integrate the code, but the feature. The idea is that if the RFC passes, then the feature is agreed, and we still have some time to find a better implementation. If we could not find one, then the feature should be abandoned or post-poned until a new patch. If the new patch changes the implementation, then the RFC should be reopened. My thoughts. Julien.Pauli

Joe Watkins

10 years ago
Morning internals, I have improved the performance of the patch a little, here's the results of a bad run: krakjoe@fiji:/usr/src/php-src$ sapi/cli/php -n prop.php empty_loop 0.064 write_prop1() 0.088 0.025 write_prop2() 0.079 0.016 write_prop3() 0.082 0.018 ------------------------ Total 0.314 There is going to be overhead, not the kind we can't minimize, or justify though. Dmitry has said he'll review, and I'm hoping at least Laruence, Nikita, and Bob will do the same ... We have many weeks to improve the implementation, I'm not going to merge anything that's obviously bad :) Cheers Joe On Mon, May 23, 2016 at 10:54 AM, Julien Pauli <jpauli@php.net> wrote:

Dmitry Stogov

10 years ago
Hi Joe, Unfortunately your solution with IS_TYPE_VERIFIED is not acceptable, because you update the source zval. If the assigned value is a literal you change read-only memory and crash (with opcache.ptotect_memory=1) <?php class C { public int $a; } $x = new C; $x->a = 5; ?> Thanks. Dmitry. ________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Monday, May 23, 2016 1:16:22 PM To: Julien Pauli Cc: Stanislav Malyshev; Dmitry Stogov; PHP internals; Phil Sturgeon Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, I have improved the performance of the patch a little, here's the results of a bad run: krakjoe@fiji:/usr/src/php-src$ sapi/cli/php -n prop.php empty_loop 0.064 write_prop1() 0.088 0.025 write_prop2() 0.079 0.016 write_prop3() 0.082 0.018 ------------------------ Total 0.314 There is going to be overhead, not the kind we can't minimize, or justify though. Dmitry has said he'll review, and I'm hoping at least Laruence, Nikita, and Bob will do the same ... We have many weeks to improve the implementation, I'm not going to merge anything that's obviously bad :) Cheers Joe On Mon, May 23, 2016 at 10:54 AM, Julien Pauli <jpauli@php.net<mailto:jpauli@php.net>> wrote: On Mon, May 23, 2016 at 11:09 AM, Stanislav Malyshev <smalyshev@gmail.com<mailto:smalyshev@gmail.com>> wrote:
> Hi! > >> The performance effect of this implementation is terrible. >> >> Assignment to typed property is 2.3 times slower. >> Assignment to untyped property in a class with typed properties is 1.8 times slower. >> >> See the benchmark >> https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 > > This is not good. I wonder why these tests weren't made before the vote > and results wheren't added in the RFC. Should we make it a standard > practice to do so? Having 2x slowdown on each property access sounds > like a bad idea.
The question is : * should the vote be an idea-based vote, or integrate the code into the vote ? My vote did not integrate the code, but the feature. The idea is that if the RFC passes, then the feature is agreed, and we still have some time to find a better implementation. If we could not find one, then the feature should be abandoned or post-poned until a new patch. If the new patch changes the implementation, then the RFC should be reopened. My thoughts. Julien.Pauli

Dmitry Stogov

10 years ago
After the latest changes the patch became better. From a quick look I see two issues. The following 3 tests are failed (crashed with opcache.protect_memory=1)
> Test typed properties float widen at runtime [Zend/tests/type_declarations/typed_properties_027.phpt] > Test typed properties respect strict types (off) [Zend/tests/type_declarations/typed_properties_028.phpt] > Test typed properties unset __get magical magic [Zend/tests/type_declarations/typed_properties_030.phpt]
Insignificant white space changes and reformatting should be removed from the patch (this would simplify the review). I'll need to take a deeper look once again, after the opcache compatibility fix. Thanks. Dmitry. ________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Monday, May 23, 2016 1:16:22 PM To: Julien Pauli Cc: Stanislav Malyshev; Dmitry Stogov; PHP internals; Phil Sturgeon Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, I have improved the performance of the patch a little, here's the results of a bad run: krakjoe@fiji:/usr/src/php-src$ sapi/cli/php -n prop.php empty_loop 0.064 write_prop1() 0.088 0.025 write_prop2() 0.079 0.016 write_prop3() 0.082 0.018 ------------------------ Total 0.314 There is going to be overhead, not the kind we can't minimize, or justify though. Dmitry has said he'll review, and I'm hoping at least Laruence, Nikita, and Bob will do the same ... We have many weeks to improve the implementation, I'm not going to merge anything that's obviously bad :) Cheers Joe On Mon, May 23, 2016 at 10:54 AM, Julien Pauli <jpauli@php.net<mailto:jpauli@php.net>> wrote: On Mon, May 23, 2016 at 11:09 AM, Stanislav Malyshev <smalyshev@gmail.com<mailto:smalyshev@gmail.com>> wrote:
> Hi! > >> The performance effect of this implementation is terrible. >> >> Assignment to typed property is 2.3 times slower. >> Assignment to untyped property in a class with typed properties is 1.8 times slower. >> >> See the benchmark >> https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 > > This is not good. I wonder why these tests weren't made before the vote > and results wheren't added in the RFC. Should we make it a standard > practice to do so? Having 2x slowdown on each property access sounds > like a bad idea.
The question is : * should the vote be an idea-based vote, or integrate the code into the vote ? My vote did not integrate the code, but the feature. The idea is that if the RFC passes, then the feature is agreed, and we still have some time to find a better implementation. If we could not find one, then the feature should be abandoned or post-poned until a new patch. If the new patch changes the implementation, then the RFC should be reopened. My thoughts. Julien.Pauli

Pierre Joye

10 years ago
On May 23, 2016 4:09 PM, "Stanislav Malyshev" <smalyshev@gmail.com> wrote:
> > Hi! > > > The performance effect of this implementation is terrible. > > > > Assignment to typed property is 2.3 times slower. > > Assignment to untyped property in a class with typed properties is 1.8
times slower.
> > > > See the benchmark > > https://gist.github.com/dstogov/1b678712adeee51665cdd829195bb800 > > This is not good. I wonder why these tests weren't made before the vote > and results wheren't added in the RFC. Should we make it a standard > practice to do so? Having 2x slowdown on each property access sounds > like a bad idea.
Agreed. We added a performance impact section to the rfc template for this exact reason. We do not enforce it. Maybe we should.

Rowan Collins

10 years ago
On 20/05/2016 07:05, Joe Watkins wrote:
> Morning internals, > > Since we have our answer on nullable types, typed properties can now go > to vote. > > https://wiki.php.net/rfc/typed-properties#vote > > Note that, support for nullability as RFC'd will be merged when the > implementation for nullable_types is merged into master. > > Please participate. > > Cheers > Joe
I'm surprised at how popular this RFC has been; not because I think it's a bad thing per se, but I thought it would be more controversial. I do still think PHP should have a proper road map for typing features, though. The issues around typed references in this RFC are a good example of how having an increasing number of silos where type enforcement takes place leads to odd inconsistencies and limitations. It would be nice to have some idea of what the eventual aim is - even if we don't know how yet, is the aim in people's minds for "optional typing" to extend throughout the language? This would also help with performance considerations - if type-checking is going to become a more important concept in the language, the engine should move in a direction which will make that easier, and that may affect optimisation decisions. Regards,
-- Rowan Collins [IMSoP]

Dmitry Stogov

10 years ago
Should this work? <?php class C { public double $x; } $o = new C; $o->x = 5; ?> Currently this leads to PHP Fatal error: Uncaught TypeError: Typed property C::$x must be an instance of double, integer used in /home/dmitry/php/php-master/CGI-DEBUG/prop.php:6 ________________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe

Niklas Keller

10 years ago
Dmitry Stogov <dmitry@zend.com> schrieb am Mo., 23. Mai 2016 14:48:
> Should this work? > > <?php > class C { > public double $x; > } > $o = new C; > $o->x = 5; > ?> > > Currently this leads to PHP Fatal error: Uncaught TypeError: Typed > property C::$x must be an instance of double, integer used in > /home/dmitry/php/php-master/CGI-DEBUG/prop.php:6 >
Do you mean "float"?

Dmitry Stogov

10 years ago
Yeah "float". It works :) ________________________________ From: Niklas Keller <me@kelunik.com> Sent: Monday, May 23, 2016 4:46:59 PM To: Dmitry Stogov; Joe Watkins; PHP internals; Phil Sturgeon Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties Dmitry Stogov <dmitry@zend.com<mailto:dmitry@zend.com>> schrieb am Mo., 23. Mai 2016 14:48: Should this work? <?php class C { public double $x; } $o = new C; $o->x = 5; ?> Currently this leads to PHP Fatal error: Uncaught TypeError: Typed property C::$x must be an instance of double, integer used in /home/dmitry/php/php-master/CGI-DEBUG/prop.php:6 Do you mean "float"? ________________________________________ From: Joe Watkins <pthreads@pthreads.org<mailto:pthreads@pthreads.org>> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php

Dmitry Stogov

10 years ago
Hi Joe, I've add implementation for nullable typed properties (as they fit into the patch design), but RFC missed any description of nullable properties. See tests Zend/tests/type_declarations/typed_properties_047.phpt, Zend/tests/type_declarations/typed_properties_048.phpt, Zend/tests/type_declarations/typed_properties_049.phpt I'm not sure, if this is what the voters expect. At least I don't like the facts that "?int $foo;" declares uninitialized property; "?int $foo = NULL" may be unset() and became uninitialized; and it's an open question if "int $foo = NULL;" should be supported as nullable. Inheritance rules for typed nullable properties are also missed. Personally, I think the RFC was moved into voting state too early (without good enough implementation, and with missing topics). The current implementation is better (performance penalty reduced to ~2%), but still have unsolved problems. May be it's better to cancel voting, solve problems, finish the implementation and add missing questions into RFC... I'm going to help with implementation in any case, but we should agree on what we are doing. Thanks. Dmitry. ________________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Friday, May 20, 2016 9:05:34 AM To: PHP internals; Phil Sturgeon Subject: [PHP-DEV] [RFC][Vote] Typed Properties Morning internals, Since we have our answer on nullable types, typed properties can now go to vote. https://wiki.php.net/rfc/typed-properties#vote Note that, support for nullability as RFC'd will be merged when the implementation for nullable_types is merged into master. Please participate. Cheers Joe

Joe Watkins

10 years ago
Morning Dmitry, There's no section for nullables, but there is mention of them, specifically in relation to your query:
> While parameters allow null to be accepted as the default value, null
is only a valid value for nullable properties. Is there something wrong with that rule ? Having explicit nullability means the declaration tells you all you need to know, all the time. Being able to set null any typed property means you can never be sure of the type; You can't tell by looking at the declaration what type the variable will be because anything is allowed to set it null. We waited for explicit nullability to avoid this. You'll have to have a really good reason for me to change that rule :)
> Inheritance rules for typed nullable properties are also missed.
That's true, but shouldn't they use the same rules as nullable parameters, will discussion change how they should work ?
> but still have unsolved problems.
If you have discussed these somewhere, can you send/show the transcript ? (I missed all comms after yesterday morning, due to illness). If it emerges that the RFC needs to be modified heavily, then I'm happy to stop the voting. But, so far, we haven't actually deviated from the RFC, only changed implementation details that are not part of the design of the feature. Sorry if it seems like I'm missing information, I don't know what you and Bob found out yet ... I super appreciate you guys working on it, obviously. Thanks for that :) Cheers Joe On Tue, May 24, 2016 at 8:04 PM, Dmitry Stogov <dmitry@zend.com> wrote:

Dmitry Stogov

10 years ago
On 05/25/2016 09:06 AM, Joe Watkins wrote:
> Morning Dmitry, > > There's no section for nullables, but there is mention of them, > specifically in relation to your query: > > > While parameters allow null to be accepted as the default value, > null is only a valid value for nullable properties. > > Is there something wrong with that rule ?
It's OK. This just should be defined and it's defined in RFC (I missed)
> > Having explicit nullability means the declaration tells you all you > need to know, all the time. > > Being able to set null any typed property means you can never be > sure of the type; You can't tell by looking at the declaration what > type the variable will be because anything is allowed to set it null. > > We waited for explicit nullability to avoid this. > > You'll have to have a really good reason for me to change that rule :) > > > Inheritance rules for typed nullable properties are also missed. > > That's true, but shouldn't they use the same rules as nullable > parameters, will discussion change how they should work ?
I made this check(s) to be invariant. You may like to do this differently... It's better to define this in RFC, check implementation and add tests.
> > > but still have unsolved problems. > > If you have discussed these somewhere, can you send/show the > transcript ? (I missed all comms after yesterday morning, due to illness).
We are working with Bob, trying to improve the patch. I added new tests fixing the problems, and also added few comments o github.
> > If it emerges that the RFC needs to be modified heavily, then I'm > happy to stop the voting.
RFC doesn't define how uninitialized nullable typed properties should behave. class C { public $a; public int $b; public ?int $c; } $obj = new C; var_dump($obj->a); // NULL var_dump($obj->b); // throw Error("") var_dump($obj->c); // first or second??? (currently throw Error("")). $obj->$a = null; $obj->$b = null; // throw Error("") $obj->$c = null; var_dump($obj->a); // NULL var_dump($obj->b); // throw Error("") var_dump($obj->c); // NULL unset($obj->$a); unset($obj->$b); unset($obj->$c); var_dump($obj->a); // notice + NULL var_dump($obj->b); // throw Error("") var_dump($obj->c); // first or second??? (currently throw Error("")). This should be defined.
> > > But, so far, we haven't actually deviated from the RFC, only > changed implementation details that are not part of the design of the > feature.
I'm not so sure. Anyway, I hope you are better and we will able to speak today or tomorrow. Thanks. Dmitry.

Joe Watkins

10 years ago
Morning Dmitry,
> I made this check(s) to be invariant. You may like to do this
differently... I think this is what everyone expects, isn't it ? I did omit to mention that part ...
> RFC doesn't define how uninitialized nullable typed properties should
behave. It does:
> *Nullable typed properties will not raise an exception when accessed
before initialization.* It's the only bold text in the document :) It seems correct to me; We raise uninitialized exceptions to prohibit the return of null to user land, for nullable properties we don't need to do that. It does mean that ?int $foo; has an implicit default value of null, but I can't see anything wrong with that, for a nullable property. I'm open to being persuaded that is wrong. I will review comments and current patch this morning ... Cheers Joe On Wed, May 25, 2016 at 8:06 AM, Dmitry Stogov <dmitry@zend.com> wrote:

Dmitry Stogov

10 years ago
On 05/25/2016 11:30 AM, Joe Watkins wrote:
> Morning Dmitry, > > > I made this check(s) to be invariant. You may like to do this > differently... > > I think this is what everyone expects, isn't it ? > > I did omit to mention that part ... > > > RFC doesn't define how uninitialized nullable typed properties > should behave. > > It does: > > > *Nullable typed properties will not raise an exception when > accessed before initialization.* > > It's the only bold text in the document :) > > It seems correct to me; We raise uninitialized exceptions to > prohibit the return of null to user land, for nullable properties we > don't need to do that. > > It does mean that ?int $foo; has an implicit default value of null, > but I can't see anything wrong with that, for a nullable property.
OK. This is the same that I like. I'll change implementation accordingly. But what should unset() do? Currently it makes property uninitialized and then it can't accessed. I suppose it should emit notice and return NULL. I'll change this as well (in an hour). Thanks. Dmitry.

Joe Watkins

10 years ago
Morning Dmitry,
> I suppose it should emit notice and return NULL.
Yes, as untyped properties do (they would also invoke magic for unset, but defined property).
> I'll change this as well (in an hour).
Thanks ... Nullable property support was missing from the implementation, completely, because it wasn't merged at the time, but I did mention it would be added. It seems like we are changing details that should have been mentioned, we're not in some cases, just clarifying them ... but I admit it's clarification that should have been included in the RFC in some cases. I would like to know what others think about halting the vote, and reopening in a few days when we have finalized the implementation, and possibly put some finishing touches on the RFC. If a few people want that to happen, happy to do it ... personally, I don't think we've deviated from the RFC. Cheers Joe On Wed, May 25, 2016 at 9:36 AM, Dmitry Stogov <dmitry@zend.com> wrote:

Nikita Popov

10 years ago
On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org> wrote:
> Morning Dmitry, > > > I made this check(s) to be invariant. You may like to do this > differently... > > I think this is what everyone expects, isn't it ? > > I did omit to mention that part ... > > > RFC doesn't define how uninitialized nullable typed properties should > behave. > > It does: > > > *Nullable typed properties will not raise an exception when accessed > before initialization.* >
I don't agree with this choice, for three reasons: a) This unnecessarily restricts what can be expressed in the type system. With these semantics it will no longer be possible to express that a property should be nullable, but have no default value. This situation is not uncommon in practice, in particular anytime you have a nullable constructor argument, you will want the corresponding property to be nullable without a default, to ensure that it is explicitly initialized. b) This directly contradicts the meaning of ?Type for parameters. For parameters ?Type means that it's a nullable parameter **without a default value**. That's the very thing that distinguishes it from the Type $prop = null syntax. And now ?Type for properties should mean the exact opposite? c) If you view this in a larger scope of union types, this *special case* becomes even more weird. Why does the particular union Type|null get special treatment, while all other unions don't? Or is it actually not specific to "null", but to single value types? E.g. if we also allowed Type|false, would that also receive an implicit false default value? What about the type null|false? Does that get an implicit default, and if so, which? I realize this is not quite in scope for type properties, but the further evolution of the type system should be kept in mind. Please keep things consistent: If there is not default, there is no default. Nikita

Joe Watkins

10 years ago
Morning Nikita, That's pretty persuasive ... Dmitry, what are your thoughts on those points ? Cheers Joe On Wed, May 25, 2016 at 2:03 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:

Dmitry Stogov

10 years ago
I thought about a different approach :) - not-nullable typed properties must be explicitly initialized (or should be initialized implicitly by corresponding types, e.g. "int" should get default value int(0). ...) - nullable typed properties may be implicitly initialized by NULL (like untyped properties now). - unset() of typed properties should not be allowed This would allow to eliminate few weird run-time checks in VM and allow the most efficient usage of type information in Optimizar and JIT. Thanks. Dmitry. ________________________________ From: Joe Watkins <pthreads@pthreads.org> Sent: Wednesday, May 25, 2016 4:22:02 PM To: Nikita Popov Cc: Dmitry Stogov; PHP internals; Phil Sturgeon; Bob Weinand Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties Morning Nikita, That's pretty persuasive ... Dmitry, what are your thoughts on those points ? Cheers Joe On Wed, May 25, 2016 at 2:03 PM, Nikita Popov <nikita.ppv@gmail.com<mailto:nikita.ppv@gmail.com>> wrote: On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org<mailto:pthreads@pthreads.org>> wrote: Morning Dmitry,
> I made this check(s) to be invariant. You may like to do this
differently... I think this is what everyone expects, isn't it ? I did omit to mention that part ...
> RFC doesn't define how uninitialized nullable typed properties should
behave. It does:
> *Nullable typed properties will not raise an exception when accessed
before initialization.* I don't agree with this choice, for three reasons: a) This unnecessarily restricts what can be expressed in the type system. With these semantics it will no longer be possible to express that a property should be nullable, but have no default value. This situation is not uncommon in practice, in particular anytime you have a nullable constructor argument, you will want the corresponding property to be nullable without a default, to ensure that it is explicitly initialized. b) This directly contradicts the meaning of ?Type for parameters. For parameters ?Type means that it's a nullable parameter **without a default value**. That's the very thing that distinguishes it from the Type $prop = null syntax. And now ?Type for properties should mean the exact opposite? c) If you view this in a larger scope of union types, this *special case* becomes even more weird. Why does the particular union Type|null get special treatment, while all other unions don't? Or is it actually not specific to "null", but to single value types? E.g. if we also allowed Type|false, would that also receive an implicit false default value? What about the type null|false? Does that get an implicit default, and if so, which? I realize this is not quite in scope for type properties, but the further evolution of the type system should be kept in mind. Please keep things consistent: If there is not default, there is no default. Nikita

Rouven Weßling

10 years ago
> On 25 May 2016, at 16:56, Dmitry Stogov <dmitry@zend.com> wrote: > > - unset() of typed properties should not be allowed
Potentially opening a larger can of worms: what is the use case of unsetting any declared property? Changing this would of course be a huge BC break but it seems less weird then having different rules for typed vs untyped properties. Cheers, Rouven

Unnamed Person

10 years ago
Hi Dmitry,
> > I thought about a different approach :) > > > - not-nullable typed properties must be explicitly initialized (or > should be initialized implicitly by corresponding types, e.g. "int" > should get default value int(0). ...) > > - nullable typed properties may be implicitly initialized by NULL > (like untyped properties now). > > - unset() of typed properties should not be allowed > > > This would allow to eliminate few weird run-time checks in VM and > allow the most efficient usage of type information in Optimizar and > JIT.
For scalar types, that's fine but, in practice, it forces object properties to be nullable, as they cannot be initialized explicitely. Regards François

Andrew Faulds

10 years ago
Hi, Nikita Popov wrote:
> On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org> wrote: > >> > *Nullable typed properties will not raise an exception when accessed >> before initialization.* >> > > I don't agree with this choice, for three reasons: > > a) This unnecessarily restricts what can be expressed in the type system. > With these semantics it will no longer be possible to express that a > property should be nullable, but have no default value. This situation is > not uncommon in practice, in particular anytime you have a nullable > constructor argument, you will want the corresponding property to be > nullable without a default, to ensure that it is explicitly initialized.
I agree with you here. In some cases, there are *three* potential meaningful states for a property: * uninitialised - the constructor (or indeed, other code) is yet to set it * null - the property is left intentionally empty * some other value - the property is intentionally given a value A simple example might be a Lisp-style linked list cell: class LinkedList { public int $head; public ?LinkedList $tail; } In a properly initialised LinkedList, the $head is some value, and the $tail is either another linked list (the remainder of the list), or null (we're at the end of the list). Before the LinkedList is initialised, ideally both properties would be undefined. That way, if we make a mistake and fail to explicitly set either in our code, PHP will give us an error message. However, the currently proposed behaviour would mean that this will only happen for $head, and PHP will fill in null for $tail for us. Notice that in this class, we aren't using null to mean a property that hasn't yet been set. Instead, we're using it to mean a property that's been deliberately left unfilled. So PHP has assumed for us that if we forget to set $tail, the remainder of the list is empty. Yet PHP assumed that if we forget to set $head, that's a mistake and must produce an error. This inconsistency of assumptions is unhelpful, and I don't see how this follows from the types I declared. I don't understand why nullable properties have to behave differently here, anyway. Doesn't it add complexity to the implementation to handle them differently from non-nullable typed properties? Doesn't it introduce inconsistency to assume a default value for nullable typed properties, but not for non-nullable ones?
> b) This directly contradicts the meaning of ?Type for parameters. For > parameters ?Type means that it's a nullable parameter **without a default > value**. That's the very thing that distinguishes it from the Type $prop = > null syntax. And now ?Type for properties should mean the exact opposite?
Given typed properties look much like typed parameters, it would be reasonable for users to expect that they behave the same, so this is a good point.
> c) If you view this in a larger scope of union types, this *special case* > becomes even more weird. Why does the particular union Type|null get > special treatment, while all other unions don't? Or is it actually not > specific to "null", but to single value types? E.g. if we also allowed > Type|false, would that also receive an implicit false default value? What > about the type null|false? Does that get an implicit default, and if so, > which? I realize this is not quite in scope for type properties, but the > further evolution of the type system should be kept in mind.
This bothers me also. Thanks!
-- Andrea Faulds https://ajf.me/

Stas Malyshev

10 years ago
Hi!
> * uninitialised - the constructor (or indeed, other code) is yet to set it > * null - the property is left intentionally empty
For declared properties, this always has been the same, and I'm not sure why would we want to change that. This also has a potential to be a huge BC break if we change it not to be the same, since pretty much all the code assumes it is the same. We'd essentially have to invent another null, which is exactly the same as null but isn't null. I don't see a reason to do this.
> * some other value - the property is intentionally given a value > > A simple example might be a Lisp-style linked list cell: > > class LinkedList > { > public int $head; > public ?LinkedList $tail; > } > > In a properly initialised LinkedList, the $head is some value, and the > $tail is either another linked list (the remainder of the list), or null > (we're at the end of the list).
This is a very weird list, as it can't be empty.
-- Stas Malyshev smalyshev@gmail.com

Andrew Faulds

10 years ago
Hi Stas, Stanislav Malyshev wrote:
> Hi! > >> * uninitialised - the constructor (or indeed, other code) is yet to set it >> * null - the property is left intentionally empty > > For declared properties, this always has been the same, and I'm not sure > why would we want to change that. This also has a potential to be a huge > BC break if we change it not to be the same, since pretty much all the > code assumes it is the same. We'd essentially have to invent another > null, which is exactly the same as null but isn't null. I don't see a > reason to do this.
It'd be a BC break if we changed untyped properties' behaviour, yeah. We wouldn't be inventing a new null, though, we'd be leaving the property undefined until it's initialised, which we already have support for (properties, and indeed all variables can be unset()).
> >> * some other value - the property is intentionally given a value >> >> A simple example might be a Lisp-style linked list cell: >> >> class LinkedList >> { >> public int $head; >> public ?LinkedList $tail; >> } >> >> In a properly initialised LinkedList, the $head is some value, and the >> $tail is either another linked list (the remainder of the list), or null >> (we're at the end of the list). > > This is a very weird list, as it can't be empty.
The empty list is represented by null in this arrangement. Thanks.
-- Andrea Faulds https://ajf.me/

Stas Malyshev

10 years ago
Hi!
> It'd be a BC break if we changed untyped properties' behaviour, yeah. We
It's not that simple. Lots of code operates on sets of properties or dynamic properties, not one specific property. That code now assumes properties default to null. If there's another default, then all that code will have to be changed in case somebody somewhere defines a typed property. The impact is that as soon as one typed property appears anywhere in the code, pretty much all the code that deals with properties (within affected property set) has to be changed to accommodate it. Unlike parameters, which are local to function, properties are important across big chunks of the code.
> wouldn't be inventing a new null, though, we'd be leaving the property > undefined until it's initialised, which we already have support for > (properties, and indeed all variables can be unset()).
unset() now causes the property to disappear - as if it were never defined. But you probably expect something different? So what isset() would return for such property? What would is_null() return? What would gettype() return?
>>> A simple example might be a Lisp-style linked list cell: >>> >>> class LinkedList >>> { >>> public int $head; >>> public ?LinkedList $tail; >>> } >>> >>> In a properly initialised LinkedList, the $head is some value, and the >>> $tail is either another linked list (the remainder of the list), or null >>> (we're at the end of the list). >> >> This is a very weird list, as it can't be empty. > > The empty list is represented by null in this arrangement.
null and empty list are very different thing. null is nothing, empty list is an object of type LinkedList which just happens to not contain any values. You can call methods on empty list - e.g. add elements to it or check if it's empty or compare or concatenate with other list, etc. - but you can't do it on null. Making assumption that null and an empty container is the same is not a good idea usually.
-- Stas Malyshev smalyshev@gmail.com

Niklas Keller

10 years ago
> > On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org> > wrote: > > > Morning Dmitry, > > > > > I made this check(s) to be invariant. You may like to do this > > differently... > > > > I think this is what everyone expects, isn't it ? > > > > I did omit to mention that part ... > > > > > RFC doesn't define how uninitialized nullable typed properties > should > > behave. > > > > It does: > > > > > *Nullable typed properties will not raise an exception when accessed > > before initialization.* > > > > I don't agree with this choice, for three reasons: > > a) This unnecessarily restricts what can be expressed in the type system. > With these semantics it will no longer be possible to express that a > property should be nullable, but have no default value. This situation is > not uncommon in practice, in particular anytime you have a nullable > constructor argument, you will want the corresponding property to be > nullable without a default, to ensure that it is explicitly initialized. >
I disagree here. Properties are always null by default. The current patch disallows access to uninitialized variables only if they're not nullable, since null isn't a valid value then. I don't think having to explicitly set them to null is the think we want. And it's not what I'd expect given the current system.
> b) This directly contradicts the meaning of ?Type for parameters. For > parameters ?Type means that it's a nullable parameter **without a default > value**. That's the very thing that distinguishes it from the Type $prop = > null syntax. And now ?Type for properties should mean the exact opposite? >
These have always been different. `private $foo` has always been `null` by default, while `function($foo)` doesn't have a default value.
> c) If you view this in a larger scope of union types, this *special case* > becomes even more weird. Why does the particular union Type|null get > special treatment, while all other unions don't? Or is it actually not > specific to "null", but to single value types? E.g. if we also allowed > Type|false, would that also receive an implicit false default value? What > about the type null|false? Does that get an implicit default, and if so, > which? I realize this is not quite in scope for type properties, but the > further evolution of the type system should be kept in mind. >
I think this is something unions should address. I'm personally still not a fan of union types, as they try to solve the wrong problem, mostly things like array not being instance of Traversable. Regards, Niklas

Andrew Faulds

10 years ago
Hi Niklas, Niklas Keller wrote:
> > I disagree here. Properties are always null by default. The current patch > disallows > access to uninitialized variables only if they're not nullable, since null > isn't a valid value then. > > I don't think having to explicitly set them to null is the think we want. > And it's not what I'd expect given the current system.
PHP's existing untyped properties are implicitly initialised to null, and so yes, we would essentially only be copying our existing behaviour. However, I think it is worth asking whether our existing behaviour is useful before we preserve it here. From my perspective, it is unhelpful that PHP does not warn you about using properties you haven't initialised, and this applies to both typed and untyped properties. In some cases (like in my linked list example in a previous email), null might be a meaningful value and worth distinguishing from a property not having being initialised yet. We can't change the behaviour of our existing untyped properties (or at least, that's beyond the scope of this RFC), but we could choose the behaviour we find more useful for our typed properties. Consider that we did something like this for parameters. Not providing an untyped parameter gives an E_WARNING: $ php -r 'function foo($a) {} foo();' PHP Warning: Missing argument 1 for foo(), called in Command line code on line 1 and defined in Command line code on line 1 But not providing a typed parameter gives a TypeError: $ php -r 'function foo(int $a) {} foo();' PHP Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be of the type integer, none given, called in Command line code on line 1 and defined in Command line code:1 Stack trace: #0 Command line code(1): foo() #1 {main} thrown in Command line code on line 1 So there's a precedent for applying stricter rules when type declarations are used. Thanks!
-- Andrea Faulds https://ajf.me/

James Gilliland

10 years ago
This is a cool idea and continuation of the typing systems so I've been sort of skimming this thread as its been discussed and this example and the associated errors caught my attention.
> class C { > public $a; > public int $b; > public ?int $c; > } > $obj = new C; >
Excuse me if this has been addressed but to clarify, using that snippet, would this also throw an error? var_dump($obj); If so, I see a lot of cursing in my future if this goes in. Like "what's the bad data on this object that's getting in here? aww #$%^ that deprecated property wasn't set so the whole thing blew up!" sort of cursing. :(

Bob Weinand

10 years ago
> Am 25.05.2016 um 17:57 schrieb James Gilliland <neclimdul@gmail.com>: > > This is a cool idea and continuation of the typing systems so I've been > sort of skimming this thread as its been discussed and this example and the > associated errors caught my attention. > >> class C { >> public $a; >> public int $b; >> public ?int $c; >> } >> $obj = new C; >> > > Excuse me if this has been addressed but to clarify, using that snippet, > would this also throw an error? > > var_dump($obj); > > If so, I see a lot of cursing in my future if this goes in. Like "what's > the bad data on this object that's getting in here? aww #$%^ that > deprecated property wasn't set so the whole thing blew up!" sort of > cursing. :(
These don't throw errors, they just won't appear upon foreach or print_r etc., just like other unset() properties. var_dump()/debug_zval_dump() are special casing it and display e.g. "uninitialized(int)" for $b. Bob

Niklas Keller

10 years ago
> > Hi Niklas, > > Niklas Keller wrote: > >> >> I disagree here. Properties are always null by default. The current patch >> disallows >> access to uninitialized variables only if they're not nullable, since null >> isn't a valid value then. >> >> I don't think having to explicitly set them to null is the think we want. >> And it's not what I'd expect given the current system. >> > > PHP's existing untyped properties are implicitly initialised to null, and > so yes, we would essentially only be copying our existing behaviour. > > However, I think it is worth asking whether our existing behaviour is > useful before we preserve it here. From my perspective, it is unhelpful > that PHP does not warn you about using properties you haven't initialised, > and this applies to both typed and untyped properties. In some cases (like > in my linked list example in a previous email), null might be a meaningful > value and worth distinguishing from a property not having being initialised > yet. >
Null shouldn't have any meaning apart from "not set". It should never be a meaningful value.

Bob Weinand

10 years ago
Hey Niklas,
> Am 25.05.2016 um 18:21 schrieb Niklas Keller <me@kelunik.com>: > >> >> Hi Niklas, >> >> Niklas Keller wrote: >> >>> >>> I disagree here. Properties are always null by default. The current patch >>> disallows >>> access to uninitialized variables only if they're not nullable, since null >>> isn't a valid value then. >>> >>> I don't think having to explicitly set them to null is the think we want. >>> And it's not what I'd expect given the current system. >>> >> >> PHP's existing untyped properties are implicitly initialised to null, and >> so yes, we would essentially only be copying our existing behaviour. >> >> However, I think it is worth asking whether our existing behaviour is >> useful before we preserve it here. From my perspective, it is unhelpful >> that PHP does not warn you about using properties you haven't initialised, >> and this applies to both typed and untyped properties. In some cases (like >> in my linked list example in a previous email), null might be a meaningful >> value and worth distinguishing from a property not having being initialised >> yet. >> > > Null shouldn't have any meaning apart from "not set". It should never be a > meaningful value. > > >> We can't change the behaviour of our existing untyped properties (or at >> least, that's beyond the scope of this RFC), but we could choose the >> behaviour we find more useful for our typed properties. >> >> Consider that we did something like this for parameters. Not providing an >> untyped parameter gives an E_WARNING: >> >> $ php -r 'function foo($a) {} foo();' >> PHP Warning: Missing argument 1 for foo(), called in Command line code on >> line 1 and defined in Command line code on line 1 >> >> But not providing a typed parameter gives a TypeError: >> >> $ php -r 'function foo(int $a) {} foo();' >> PHP Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be >> of the type integer, none given, called in Command line code on line 1 and >> defined in Command line code:1 >> Stack trace: >> #0 Command line code(1): foo() >> #1 {main} >> thrown in Command line code on line 1 >> >> So there's a precedent for applying stricter rules when type declarations >> are used. >> >> Thanks! >> >> >> -- >> Andrea Faulds >> https://ajf.me/
There is a difference between not set and no meaningful value. The former is literally unset(), the latter is null. The only semantics PHP exposes here is that not set can be upgraded to "no meaningful" value in form of null with a notice. The difference thus is quite minor, but semantically important. Hence to *set* the value, we need to explicitly set null. If we don't do it this way, we won't have a way to explicitly *set* nullable properties to a value (null in this case). (without explicit unset in ctor). Bob

Fleshgrinder

10 years ago
On 5/25/2016 5:49 PM, Andrea Faulds wrote:
> PHP's existing untyped properties are implicitly initialised to null, > and so yes, we would essentially only be copying our existing behaviour. > > However, I think it is worth asking whether our existing behaviour is > useful before we preserve it here. From my perspective, it is unhelpful > that PHP does not warn you about using properties you haven't > initialised, and this applies to both typed and untyped properties. In > some cases (like in my linked list example in a previous email), null > might be a meaningful value and worth distinguishing from a property not > having being initialised yet. > > We can't change the behaviour of our existing untyped properties (or at > least, that's beyond the scope of this RFC), but we could choose the > behaviour we find more useful for our typed properties. >
We already have the differentiation between IS_NULL and IS_UNDEF, why not expose the latter to userland? I mean, JavaScript has it too and people are able to understand it. class A { public int $x; public ?int $y = null; public int $z = 42; } $a = new A; var_dump($a->x); // undefined var_dump($a->y); // null var_dump($a->z); // 42 unset($a->z); var_dump($a->z); // undefined + error At least to me this makes sense and there would be no problem with unset() anymore. Although I truly question the usefulness of its functionality. Can anyone come up with a real world use case for unset()? Or maybe not use /undefined/ but /unset/ as a term because it is already baked in? (Well the constant IS_UNDEF should be renamed to IS_UNSET to stay consistent in all layers.) class A { public int $x; public ?int $y = null; public int $z = 42; } $a = new A; var_dump($a->x); // unset var_dump($a->y); // null var_dump($a->z); // 42 // NOT SURE IF THIS SHOULD BE POSSIBLE!!!! $a->z = (unset) $a->z; // was null (PHP<7.1) would become unset var_dump($a->z); // unset + error $a->z = unset; var_dump($a->z); // unset + error unset($a->z); var_dump($a->z); // unset + error Of course this would also requires the introduction of an unset (and UNSET) constant in userland. class A { private $x; public function getX() { if ($x === unset) { $this->x = 42; } return $this->x; } } I love the difference to null, this makes the code much more expressive. There would be the following rules: - Access always results in error. - Usage as argument results in error. - Usage as return results in error (could be void but BC). - ... more errors ... - Comparison is possible! - The following existing operations would need to be changed to make use of unset instead of null (possible BC): - unset() - (unset) cast - The following new operations would need to be introduced: - is_unset() - The following existing operations would need to be extended: - gettype() - settype()
-- Richard "Fleshgrinder" Fussenegger

Unnamed Person

10 years ago
Following "Type safety is the goal of this RFC, not validating objects.", it would be better to do implicit casting for uninitialized properties (whenever implicit casting is possible) or use null for nullable types: class A { public int $x; public ?int $y = null; public int $z = 42; public ?int $u; public ?datetime $v; public datetime $w; } $a = new A; var_dump($a->x); // 0 + notice var_dump($a->y); // null var_dump($a->z); // 42 unset($a->z); var_dump($a->z); // 0 + notice var_dump($a->u); // null + notice var_dump($a->v); // null + notice var_dump($a->w); // Fatal error, uninitialized... Regards Thomas Fleshgrinder wrote on 25.05.2016 23:03:

Stas Malyshev

10 years ago
Hi!
> We already have the differentiation between IS_NULL and IS_UNDEF, why > not expose the latter to userland? I mean, JavaScript has it too and > people are able to understand it.
IS_UNDEF is not a PHP type, it is an engine implementation flag. Now, adding a new type "undefined" would be a pretty big thing and then you'd need to deal with all the implications of it. Including a huge BC break of changing the type of all uninitialized variables, and the question of "what if I want my parameter to be able to accept undefined values" and so on. Huge can of worms, and all of it again just to have a type that is exactly like null but not null. While the only reason null exists is to do exactly what "undefined" is proposed to do.
-- Stas Malyshev smalyshev@gmail.com

Lester Caine

10 years ago
On 25/05/16 22:03, Fleshgrinder wrote:
> We already have the differentiation between IS_NULL and IS_UNDEF, why > not expose the latter to userland?
Is this not simply a mistake? The whole reason for null in my book is that it IS 'undefined'. We have to have a flag for it since you can't easily identify it as a 'value' stored im the variable. I think I can see why some people would want to know if a variable has not been initialised, but null still fits that requirement. When any variable is created it IS_NULL until such time as a value is assigned - and a type of value established. In my book an assignment will check for more than IS_INT so using typed variables is of little advantage. But if I test for a value and find null then I know it has not yet been initialised. IS_UNDEF can't exist if there is no named variable to attach it to, so user land gets an error that the variable does not exist.
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Rowan Collins

10 years ago
On 25/05/2016 22:03, Fleshgrinder wrote:
> We already have the differentiation between IS_NULL and IS_UNDEF, why > not expose the latter to userland?
I wondered if the conversation would go in this direction. This has been discussed to death, and in my opinion all the reasons given in previous discussions why isset() is not broken, and we do not need a new magic value / type, are just as valid in the case of object properties as anywhere else. I can see an advantage to this raising some kind of warning: class A { ?int $foo } $a = new A; var_dump($a->foo); // not initialized yet! But it should absolutely not be possible to detect the difference between that and this: class A { ?int $foo } $a = new A; $->foo = null; var_dump($a->foo); // null Because that is exactly the same as this: var_dump($foo); // not initialized yet! vs this: $foo = null; var_dump($foo); The warning or error on unitialized variables or properties is an assertion - code should be written such that it simply *can't* happen. If you're unsure if something's set, you can always do this: if ( ! isset($this->foo) ) { $this->foo = null; } If it's already an explicit null, you perform one unnecessary operation; if it's never been initialized, it has now. Regards,
-- Rowan Collins [IMSoP]

Tom Worster

10 years ago
On 5/25/16 9:03 AM, Nikita Popov wrote:
> On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org> wrote: > >> Morning Dmitry, >> >> > I made this check(s) to be invariant. You may like to do this >> differently... >> >> I think this is what everyone expects, isn't it ? >> >> I did omit to mention that part ... >> >> > RFC doesn't define how uninitialized nullable typed properties should >> behave. >> >> It does: >> >> > *Nullable typed properties will not raise an exception when accessed >> before initialization.* >> > > I don't agree with this choice, for three reasons: > > a) This unnecessarily restricts what can be expressed in the type system. > With these semantics it will no longer be possible to express that a > property should be nullable, but have no default value. This situation is > not uncommon in practice, in particular anytime you have a nullable > constructor argument, you will want the corresponding property to be > nullable without a default, to ensure that it is explicitly initialized. > > b) This directly contradicts the meaning of ?Type for parameters. For > parameters ?Type means that it's a nullable parameter **without a default > value**. That's the very thing that distinguishes it from the Type $prop = > null syntax. And now ?Type for properties should mean the exact opposite? > > c) If you view this in a larger scope of union types, this *special case* > becomes even more weird. Why does the particular union Type|null get > special treatment, while all other unions don't? Or is it actually not > specific to "null", but to single value types? E.g. if we also allowed > Type|false, would that also receive an implicit false default value? What > about the type null|false? Does that get an implicit default, and if so, > which? I realize this is not quite in scope for type properties, but the > further evolution of the type system should be kept in mind. > > Please keep things consistent: If there is not default, there is no default.
Object properties being in a uninitialized state is unfamiliar in current PHP practice. We are accustomed to not worrying about an "uninitialized error" when we read a property. We are assured to get either null or whatever was last written to the property. I suspect this unfamiliarity lies behind some people's preference for an implicit initial null value of a nullable typed property. But I'm inclined to agree with Nikita that the following should be different: public ?Client $mark; public ?Client $mark = null; ... and that the difference should be coherent with that between: function con(?Client $mark) {} function con(?Client $mark = null) {} ... which is that you *must* give $mark value in the first and you don't need to in the second because it has an explicit default. We are more-or-less accustomed already to the difference between: function con(Client $mark) {} function con(Client $mark = null) {} ... so I think your consistency argument is good. Moreover, the "good old" implicit initial null for untyped properties (i.e. that `public $foo;` means `public $foo = null;`) is just a lazy shortcut that I wouldn't defend except for BC, which isn't an issue here. Tom