# [RFC] Scalar Type Hinting With Casts (re-opening)

- Thread: https://externals.io/message/75683
- Original archive: https://news-web.php.net/php.internals/75683
- Started by Theodore Brown on 2014-07-18T05:02:37+00:00
- Messages: 13
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #75683 — Theodore Brown — 2014-07-18T05:02:37+00:00

URL: https://externals.io/message/75683#75683

> Since I am very much in favour of scalar type hints, I've updated the
> patch to master and made some minor improvements, and I am re-opening
> the RFC with the intent to try and get it into PHP 5.7.

First of all, this is my first reply on PHP Internals so I hope I am doing it right. :)

Thank you very much Andrea for reviving this RFC - I'm really looking forward to using 
something like this in the next version of PHP to more easily define interfaces and 
catch unintended errors in my code.

However, something I feel it is important to consider is not just how scalar type 
annotations fit into the history of PHP, but how they fit with the way type annotations 
are currently used and where the language is going in the future.

A recurring comment I've heard in the discussion for this RFC is that strict type hints
aren't "the PHP way." However, current type hints for classes, arrays, and callables 
work exactly in this way - they do not allow nulls, no casting is performed, and an 
invalid type results in a fatal error. If scalar annotations are introduced, many PHP 
developers (myself included) would naturally expect them to behave in the same way.

Another concern I have is in regard to the future. I'm looking forward to the 
possibility of specifying nullable types in a future version of PHP (see Levi Morrison's "Declaring Nullable Types" RFC: http://wiki.php.net/rfc/nullable_typehints). If the 
nullable types RFC is accepted, it would be highly disconcerting if scalar type 
annotations allowed null values regardless of whether a nullable marker is specified.

I don't think that optional strict type annotations will take away from PHP's dynamic
nature - they will instead be a valuable feature used in places where it is necessary
to strictly validate a parameter's type - this is especially important to ensuring
stability and accuracy in the large PHP applications it is my job to maintain.

The RFC has already been updated to make boolean type annotations strict. Doesn't it 
make sense to treat the other scalar types in the same way? Perhaps a future RFC could
propose a second (also optional) syntax to specify type annotations which perform casts.
However, only having cast-based annotations for scalar types would be a mistake, IMHO.

--

Theodore Brown

A PHP developer interested in the language's future

---

## #75685 — Simon Schick — 2014-07-18T07:43:56+00:00

URL: https://externals.io/message/75683#75685 · In reply to: #75683

> > […]
>
> First of all, this is my first reply on PHP Internals so I hope I am doing it right. :)
>
> Thank you very much Andrea for reviving this RFC - I'm really looking forward to using
> something like this in the next version of PHP to more easily define interfaces and
> catch unintended errors in my code.
>
> However, something I feel it is important to consider is not just how scalar type
> annotations fit into the history of PHP, but how they fit with the way type annotations
> are currently used and where the language is going in the future.
>
> A recurring comment I've heard in the discussion for this RFC is that strict type hints
> aren't "the PHP way." However, current type hints for classes, arrays, and callables
> work exactly in this way - they do not allow nulls, no casting is performed, and an
> invalid type results in a fatal error. If scalar annotations are introduced, many PHP
> developers (myself included) would naturally expect them to behave in the same way.
>
> Another concern I have is in regard to the future. I'm looking forward to the
> possibility of specifying nullable types in a future version of PHP (see Levi Morrison's "Declaring Nullable Types" RFC: http://wiki.php.net/rfc/nullable_typehints). If the
> nullable types RFC is accepted, it would be highly disconcerting if scalar type
> annotations allowed null values regardless of whether a nullable marker is specified.
>
> I don't think that optional strict type annotations will take away from PHP's dynamic
> nature - they will instead be a valuable feature used in places where it is necessary
> to strictly validate a parameter's type - this is especially important to ensuring
> stability and accuracy in the large PHP applications it is my job to maintain.
>
> The RFC has already been updated to make boolean type annotations strict. Doesn't it
> make sense to treat the other scalar types in the same way? Perhaps a future RFC could
> propose a second (also optional) syntax to specify type annotations which perform casts.
> However, only having cast-based annotations for scalar types would be a mistake, IMHO.
>
> --
>
> Theodore Brown
>
> A PHP developer interested in the language's future
>
> --
> 
> 
>

Hi, all

First of all, thanks for all your time, you put into this thread! I
really am looking forward for a way, all can live with, because this
topic has followed the PHP community since the release of PHP 5.1,
since the introduction of type hinting for arrays
(http://php.net/manual/en/language.oop5.typehinting.php).

On an archive for this mailinglist I found threads that are going back
to 2005 (http://marc.info/?l=php-internals&m=112397232722668&w=2) -
Here's a list of all messages found:
http://marc.info/?l=php-internals&s=type+hinting&q=b

I've been one of the most active contributors to a thread back in 2012
- not the one giving most productive feedback, but the one giving the
most feedback ... (I later saw a statistic of who posted the most
mails to the mailinglist within the months of discussion)

What I see, we're again stuck with mainly three different opinions, as
Paul Biggar pointed out in his post - and he tried to find a solution
back then. I would suggest that anyone should read this mail - if you
want, read the thread - I haven't had the time for now..:
http://marc.info/?l=php-internals&m=124653792412529&w=2

In every round we took this topic, there have been new RFCs added ...
I don't know if there will be a solution, and my personal favorite is
the way, proposed in this RFC here. No casting for the values, just
more a validation - a lossy validation.

The main reason for this proposal is, that mostly every input to your
application will be a string. If it now is a file, a value from the
database, the GET and POST parameters, a CURL response - nearly
anything. I don't think it makes sense to first cast them before you
can use them.

I agree, that it feels wrong to have a method, accepting
(string)"123abc" and casting it to (int)123 for internal usage, but it
also feels wrong to not let the input (string)"123" pass as a
parameter to a method accepting integer. This would lead us to casting
(f.e. substr("string", (int)$var)  ), what again would be like accept
anything ($var = "abc").

I also saw some complaining about that older code may will not work
when introducing something here. As of what I think, this should be
implemented as an extension to the language as it is now. Old code
should be able to run as it is. You may will get a problem when your
old code is using a library, that you want to update and the library
is using the new syntax ;)

Thanks for reading.

Bye
Simon

---

## #75689 — Andrea Faulds — 2014-07-18T13:09:49+00:00

URL: https://externals.io/message/75683#75689 · In reply to: #75683

> Another concern I have is in regard to the future. I'm looking forward to the 
> possibility of specifying nullable types in a future version of PHP (see Levi Morrison's "Declaring Nullable Types" RFC: http://wiki.php.net/rfc/nullable_typehints). If the 
> nullable types RFC is accepted, it would be highly disconcerting if scalar type 
> annotations allowed null values regardless of whether a nullable marker is specified.

The current proposed behaviour could be changed. At the moment, if a scalar type hint is nullable, then it won’t cast `NULL` if it’s passed that value, but if it’s not nullable, then it will cast it.

Considering how this tends to only allow lossless casts, though, it might be worth reconsidering this and just disallowing `NULL` altogether. It’s worth pointing out that `NULL` is usually an error value, and you might get it from using an uninitialised variable or calling an internal function with bad parameters.

--
Andrea Faulds
http://ajf.me/

---

## #75691 — Theodore Brown — 2014-07-18T15:46:23+00:00

URL: https://externals.io/message/75683#75691

> > […]
>
> The current proposed behaviour could be changed. At the moment, if
> a scalar type hint is nullable, then it won’t cast `NULL` if it’s
> passed that value, but if it’s not nullable, then it will cast it.
>
> Considering how this tends to only allow lossless casts, though, it
> might be worth reconsidering this and just disallowing `NULL` > altogether. It’s worth pointing out that `NULL` is usually an error
> value, and you might get it from using an uninitialised variable or
> calling an internal function with bad parameters.

The same thing applies to boolean values. `FALSE` is frequently returned
from internal functions when an error occurs, and allowing it to be
passed to a function expecting a different scalar type could mask errors.

After reading Simon's response I do feel it would be a reasonable
compromise to allow strings to be cast to int/float (and vice versa) as
long as no data loss occurs (following the current rules in the RFC).
If the RFC is updated to disallow `NULL` altogether and also disallow
boolean values for other scalar types I would be 100% supportive.

--

Theodore Brown

A PHP developer interested in the future of the language

---

## #75709 — Andrea Faulds — 2014-07-20T13:11:12+00:00

URL: https://externals.io/message/75683#75709 · In reply to: #75689

> 
> 
> > […]
> 
> The current proposed behaviour could be changed. At the moment, if a scalar type hint is nullable, then it won’t cast `NULL` if it’s passed that value, but if it’s not nullable, then it will cast it.
> 
> Considering how this tends to only allow lossless casts, though, it might be worth reconsidering this and just disallowing `NULL` altogether. It’s worth pointing out that `NULL` is usually an error value, and you might get it from using an uninitialised variable or calling an internal function with bad parameters.

I’ve updated the RFC and patch to make int, string and double nullability work like the other types (bool already did). If the default value isn’t NULL, `NULL` isn’t accepted and you’ll get E_RECOVERABLE_ERROR. If the default value is NULL, `NULL` is accepted and will not be casted.

This will likely lead to less bugs as `NULL` is a common error value, and it also makes the scalar type hints more consistent with the others.
--
Andrea Faulds
http://ajf.me/

---

## #75710 — Andrea Faulds — 2014-07-20T13:13:31+00:00

URL: https://externals.io/message/75683#75710 · In reply to: #75709

> double

Did I just say double? I meant float, of course. :)

The patch actually warns you if you try to do this now:

    function foo(double $foo) {}
    foo(1.0);

If you use one of the non-existent aliases (double), and pass the type that alias is supposed to hint for (a float), the error message notes you might be looking for the actual type hint (`float`).

The same for integer and boolean (only int and bool, respectively, are permitted).
--
Andrea Faulds
http://ajf.me/

---

## #75722 — Theodore Brown — 2014-07-20T16:26:46+00:00

URL: https://externals.io/message/75683#75722

> I’ve updated the RFC and patch to make int, string and double nullability work like the other types (bool already did). If the default value isn’t NULL, `NULL` isn’t accepted and you’ll get E_RECOVERABLE_ERROR. If the default value is NULL, `NULL` is accepted and will not be casted.
>
> This will likely lead to less bugs as `NULL` is a common error value, and it also makes the scalar type hints more consistent with the others.

Thank you very much for making this change. It goes a long way towards making scalar type annotations more useful to me as a userland developer. Also, I really like the new "numeric" type hint.

The one remaining issue I have with this proposal is that boolean values are currently accepted for every other scalar type except array. As with NULL, `FALSE` is a common error value, and allowing booleans to be passed to a function expecting a string or numeric value could easily mask errors and lead to hard-to-debug issues in a program. Just as a string cannot be passed to a function expecting a boolean, a boolean should not be passed to a function expecting a string, etc.

Thanks for all you do for the community.

--

Theodore Brown

A PHP developer interested in the future of the language

---

## #76134 — Andrea Faulds — 2014-07-25T19:00:13+00:00

URL: https://externals.io/message/75683#76134 · In reply to: #75722

> The one remaining issue I have with this proposal is that boolean values are currently accepted for every other scalar type except array. As with NULL, `FALSE` is a common error value, and allowing booleans to be passed to a function expecting a string or numeric value could easily mask errors and lead to hard-to-debug issues in a program. Just as a string cannot be passed to a function expecting a boolean, a boolean should not be passed to a function expecting a string, etc.

After consulting with Anthony about this, the RFC and patch have been updated to disallow booleans for int, float, numeric and string type hints. The conversions table now looks like this:

https://wiki.php.net/rfc/scalar_type_hinting_with_cast#conversion_rules
--
Andrea Faulds
http://ajf.me/

---

## #76135 — Stas Malyshev — 2014-07-25T19:20:33+00:00

URL: https://externals.io/message/75683#76135 · In reply to: #76134

Hi!

> After consulting with Anthony about this, the RFC and patch have been
> updated to disallow booleans for int, float, numeric and string type
> hints. The conversions table now looks like this:

This makes very little sense, 0 means the same as false is in many
contexts in PHP and also in many languages. Having random arcane rules
would only make the users curse us every time they get tripped by them.
I call everybody to vote against this RFC - it's better not to have such
thing at all then to promise our users improvement only for them to
discover this improvement is fraught with inconsistent arbitrary rules
that do not match what the rest of the language is doing - even within
the same context of the function call. I can see no uniting principle
behind this table, which is randomly strict and randomly non-strict
without connection to the rest of PHP. I do not think it is the right
thing to have such thing in the language, even if it would help
somebody's particular use-case.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/

---

## #76137 — Andrea Faulds — 2014-07-25T19:29:11+00:00

URL: https://externals.io/message/75683#76137 · In reply to: #76135

> This makes very little sense, 0 means the same as false is in many
> contexts in PHP and also in many languages.

It also means very different things in some places, particularly return values. strpos returning 0 is most definitely not the same thing as strpos returning FALSE. That’s a big reason why `FALSE` and `TRUE` aren’t accepted for int type hints: bools are common error values.

> Having random arcane rules
> would only make the users curse us every time they get tripped by them.

The rules are not random nor arcane.

> I call everybody to vote against this RFC - it's better not to have such
> thing at all then to promise our users improvement only for them to
> discover this improvement is fraught with inconsistent arbitrary rules

How are they inconsistent and arbitrary? These rules haven’t been picked at random from a hat, they’ve come from a process of careful thought. Casting an integer to a string and vice-versa makes sense and is a common operation ($_GET[‘id’]), while casting a `NULL` or `FALSE` to a string doesn’t really make sense (when do you need to do this?), and is unlikely to happen unless something’s gone wrong.

> that do not match what the rest of the language is doing

That is true, but it would be possible to change zpp later.

> - even within
> the same context of the function call. I can see no uniting principle
> behind this table, which is randomly strict and randomly non-strict
> without connection to the rest of PHP. I do not think it is the right
> thing to have such thing in the language, even if it would help
> somebody's particular use-case.

The point of this RFC is to strike a compromise that is generally useful rather than helping one specific use case (strict hints) or another (casts).

--
Andrea Faulds
http://ajf.me/

---

## #76138 — Stas Malyshev — 2014-07-25T19:41:03+00:00

URL: https://externals.io/message/75683#76138 · In reply to: #76137

Hi!

> The point of this RFC is to strike a compromise that is generally
> useful rather than helping one specific use case (strict hints) or
> another (casts).

What you call "compromise" is the inconsistency - it's not strict
typing, it's not weak typing, it's half that and half this without any
apparent principle uniting them but arbitrarily constructed table, to
which anybody using it would have to constantly refer to figure out why
their code is breaking. I'm sure you carefully thought about each and
every cell in that table, but that does not make it any better for the
user - in fact, it makes it worse, since absent the obvious uniting
principle it means each time the user encounters it it has to
reconstruct the long and laborious thought process anew or just learn
the whole table by hard. It is not a good design. Good design is where
you can predict what the language would do without remembering a bunch
of exceptions that are just so.

Even worse, it does not match what other functions are doing and what
other type conversions are doing. It's like a "compromise" of cutting
the baby in half - much worse than any of the original proposals. Only
in the case of Solomon it was a trick, you on the other side propose it
as a serious and preferable solution. This kind of "compromise" is not a
positive thing, but a negative.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/

---

## #76139 — Zeev Suraski — 2014-07-25T19:57:17+00:00

URL: https://externals.io/message/75683#76139 · In reply to: #76138

> 
>
> Hi!
>
> > […]
>
> What you call "compromise" is the inconsistency - it's not strict
> typing, it's not weak typing, it's half that and half this without any
> apparent principle uniting them but arbitrarily constructed table, to
> which anybody using it would have to constantly refer to figure out why
> their code is breaking.

Well put.

Zeev

---

## #76141 — Christoph Becker — 2014-07-25T20:09:03+00:00

URL: https://externals.io/message/75683#76141 · In reply to: #76137

Andrea Faulds wrote:

> 
> 
> > […]
> 
> That is true, but it would be possible to change zpp later.

IMHO it might be a good idea to have a respective RFC wrt. ZPP first.
It might be possible and sensible to change ZPP for PHP NEXT.  If that
RFC would pass, it makes sense to use these rules for the type hints,
what might be already introduced in PHP 5.7 (if this version will be
released).

-- 
Christoph M. Becker
