Nullable types and strict type-hinting with default null value

php.internals

Michał

9 years ago
Hello PHP internals, Scalar types declarations were introduced in PHP 7.0 but it was not possible to pass null as a default value to function/method. It was finally done by a small workaround described in documentation as "The declaration can be made to accept NULL values if the default value of the parameter is set to NULL". In PHP 7.1 and it's new feature - nullable types - this hack is, in my opinion, completely unnecessary. It breaks valid type-hinting, is not logical for advanced programmers, and may cause potential bugs. According to docs "Type declarations allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.". Following this, first line of code should throw error - but it does not, because of 7.0 work-around. a(string $test=null) // incorrect type, should throw error a(string $test='test') // valid type, ok a(?string $test=null) // valid type, ok a(?string $test='test') // valid type, ok There is no reason, except of backwards compatibility, to keep this behaviour. It's too late to change this in 7.1, maybe even in 7.2. But, what is Your opinion? Should it be preserved or fixed?

Andrey Andreev

9 years ago
Hi, On Wed, Feb 22, 2017 at 11:18 PM, Michał <aaatoja@o2.pl> wrote:
> Hello PHP internals, > Scalar types declarations were introduced in PHP 7.0 but it was not > possible to pass null as a default value to function/method. It was finally > done by a small workaround described in documentation as "The declaration > can be made to accept NULL values if the default value of the parameter is > set to NULL". > > In PHP 7.1 and it's new feature - nullable types - this hack is, in my > opinion, completely unnecessary. It breaks valid type-hinting, is not > logical for advanced programmers, and may cause potential bugs. According > to docs "Type declarations allow functions to require that parameters are > of a certain type at call time. If the given value is of the incorrect > type, then an error is generated: in PHP 5, this will be a recoverable > fatal error, while PHP 7 will throw a TypeError exception.". Following > this, first line of code should throw error - but it does not, because of > 7.0 work-around. > > a(string $test=null) // incorrect type, should throw error > a(string $test='test') // valid type, ok > a(?string $test=null) // valid type, ok > a(?string $test='test') // valid type, ok > > There is no reason, except of backwards compatibility, to keep this > behaviour. It's too late to change this in 7.1, maybe even in 7.2. But, > what is Your opinion? Should it be preserved or fixed? >
This isn't just a PHP 7 work-around for null types, it has existed since object type hints were introduced and is very widespread. Cheers, Andrey.

Rowan Collins

9 years ago
On 23 February 2017 07:23:02 GMT+00:00, Andrey Andreev <narf@devilix.net> wrote:
>Hi, > >On Wed, Feb 22, 2017 at 11:18 PM, Michał <aaatoja@o2.pl> wrote: > >> "The >declaration >> can be made to accept NULL values if the default value of the >parameter is >> set to NULL". > >This isn't just a PHP 7 work-around for null types, it has existed >since >object type hints were introduced and is very widespread.
Indeed, it's far too early to think about forcing people to change all their code to the ? notation. I'm also not convinced of the value even once that's established; it's not like "Foo $foo = null" can ever mean *something different* from "?Foo $foo = null", it would just be an error. Maybe in 10 years' time we'll have another bonfire of unused features, and this might be one, but it's not something we can plan for right now. Regards,
-- Rowan Collins [IMSoP]

Michał

9 years ago
> Indeed, it's far too early to think about forcing people to change all their code to the ? notation. I'm also not convinced of the value even once that's established; it's not like "Foo $foo = null" can ever mean *something different* from "?Foo $foo = null", it would just be an error. > > Maybe in 10 years' time we'll have another bonfire of unused features, and this might be one, but it's not something we can plan for right now. >
And what about situation when someone is forcing declare(strict_types=1)? I think, it's really a good place to force proper types. Including nulls.

Rowan Collins

9 years ago
On 23 February 2017 09:15:27 GMT+00:00, "Michał" <aaatoja@o2.pl> wrote:
>And what about situation when someone is forcing >declare(strict_types=1)? I think, it's really a good place to force >proper types. Including nulls.
strict_types controls the behaviour of *calling* functions, but the check here would have to be when *defining* the function: it would give an error that the function definition is invalid, like if you say function foo(int $bar='hello') Unless you had some other behaviour in mind? Regards,
-- Rowan Collins [IMSoP]

Andrew Faulds

9 years ago
Hi, Rowan Collins wrote:
> On 23 February 2017 09:15:27 GMT+00:00, "Michał" <aaatoja@o2.pl> wrote: >> And what about situation when someone is forcing >> declare(strict_types=1)? I think, it's really a good place to force >> proper types. Including nulls. > > strict_types controls the behaviour of *calling* functions, but the check here would have to be when *defining* the function: it would give an error that the function definition is invalid, like if you say function foo(int $bar='hello') > > Unless you had some other behaviour in mind?
In addition to this, if we wanted to prohibit implicit nullability in parameter definitions, we should have done it when we introduced declare(strict_types=1); in the first place, and that ship has sailed.
-- Andrea Faulds https://ajf.me/

Niklas Keller

9 years ago
2017-02-25 16:12 GMT+01:00 Andrea Faulds <ajf@ajf.me>:
> Hi, > > Rowan Collins wrote: > >> On 23 February 2017 09:15:27 GMT+00:00, "Michał" <aaatoja@o2.pl> wrote: >> >>> And what about situation when someone is forcing >>> declare(strict_types=1)? I think, it's really a good place to force >>> proper types. Including nulls. >>> >> >> strict_types controls the behaviour of *calling* functions, but the check >> here would have to be when *defining* the function: it would give an error >> that the function definition is invalid, like if you say function foo(int >> $bar='hello') >> >> Unless you had some other behaviour in mind? >> > > In addition to this, if we wanted to prohibit implicit nullability in > parameter definitions, we should have done it when we introduced > declare(strict_types=1); in the first place, and that ship has sailed.
At that point we didn't even have nullable types, yet. Also, strict_types should do one thing, not all the things related to types.

Andrew Faulds

9 years ago
Hi, Niklas Keller wrote:
> 2017-02-25 16:12 GMT+01:00 Andrea Faulds <ajf@ajf.me>: > >> Rowan Collins wrote: >> >>> On 23 February 2017 09:15:27 GMT+00:00, "Michał" <aaatoja@o2.pl> wrote: >>> >>>> And what about situation when someone is forcing >>>> declare(strict_types=1)? I think, it's really a good place to force >>>> proper types. Including nulls. >>>> >>> >>> strict_types controls the behaviour of *calling* functions, but the check >>> here would have to be when *defining* the function: it would give an error >>> that the function definition is invalid, like if you say function foo(int >>> $bar='hello') >>> >>> Unless you had some other behaviour in mind? >>> >> >> In addition to this, if we wanted to prohibit implicit nullability in >> parameter definitions, we should have done it when we introduced >> declare(strict_types=1); in the first place, and that ship has sailed. > > > At that point we didn't even have nullable types, yet.
Sure.
> > Also, strict_types should do one thing, not all the things related to types. >
I don't disagree. My point is that now that strict_types has been introduced, we have to maintain backwards-compatibility with code that uses it currently. We can't just tack new behaviour changes onto it without careful consideration, because that can break existing strict_types code.
-- Andrea Faulds https://ajf.me/

Levi Morrison

9 years ago
On Wed, Feb 22, 2017 at 2:18 PM, Michał <aaatoja@o2.pl> wrote:
> a(string $test=null) // incorrect type, should throw error > > There is no reason, except of backwards compatibility, to keep this > behaviour. It's too late to change this in 7.1, maybe even in 7.2. But, what > is Your opinion? Should it be preserved or fixed?
My opinion is that it is far too early to try to change it in any way. Maybe in PHP version 8.0 we could add an E_DEPRECATED or E_STRICT but it's far too early to do anything in the 7.X series.

Stas Malyshev

9 years ago
Hi!
> Scalar types declarations were introduced in PHP 7.0 but it was not > possible to pass null as a default value to function/method. It was > finally done by a small workaround described in documentation as "The > declaration can be made to accept NULL values if the default value of > the parameter is set to NULL".
If removing it would make scalar types work differently from non-scalar types, it's not a good idea. Also, I don't see a reason why not have both declarations mean nullable type - the intent is clear in both cases, it's not like it can be confused with something else.
-- Stas Malyshev smalyshev@gmail.com