Thank you so much for taking the time to do this. Your explanations of a
more "real-world" example are extremely valuable and provide a very strong
hint at the effects that these RFC implementations may have, both in the
short and long term.

Seriously, very appreciated.

On Thu, Feb 26, 2015 at 7:30 PM Matthew Weier O'Phinney <matt...@zend.com>
wrote:

> I've taken some time the last couple days to compile both the Scalare Type
> Hints
> v0.5 (heretofor STHv5) and Coercive Scalar Type Hints (heretofore
> STHcoerce)
> patches and test some code against them.
>
> In each case, I modified the `Phly\Http\Response` class from my phly/http
> package to add scalar type hints, remove previous argument validation, and
> then
> ran the unit tests. Here's my details of the experience, and analysis.
>
> ### STHv5
>
> With STHv5, my tests failed out of the box. First, I needed to add an error
> handler that would convert the E_RECOVERABLE_ERROR to an
> InvalidArgumentException so that I would get useful error messages from
> PHPUnit.
> Next, once I had done that, I had tests that were throwing invalid input at
> methods, and validating that the invalid arguments were caught. This
> worked in
> all but one specific case: passing a float value to an argument expecting
> an
> integer. In this particular case, the value was coerced to an integer,
> albeit
> lossily, and no error was raised.
>
> When I changed my test case to operate under strict_types mode, the test
> executed as I had originally expected, and succeeded.
>
> #### Analysis
>
> I did not expect the float value to be coerced, particularly as it had a
> fractional part. Yes, I understand that this is how casting _currently_
> works in
> PHP, and that the patch uses the current casting rules. However, I'd
> expect that
> any float with a fractional value would not be cast to an integer; doing
> so is
> lossy, and can lead to unexpected results.
>
> The strict_types mode operated how I would expect it, but meant I was
> forced to
> add the declaration to the top of the file. Which leads to this:
>
> My tests operated differently in strict vs normal mode. That means my code
> does,
> too. Testing both modes would be difficult to do in an automated fashion;
> essentially, you're left needing to choose to support one mode or the
> other.
> This goes back to the point I was making earlier this week: I worry that
> having
> two modes will lead to a schism in userland libraries: those that support
> strict, and those that do not; there will be little possibility of testing
> both.
>
> ### STHcoerce
>
> With STHcoerce, my tests also failed out of the box, but not for the same
> reason. Instead, I had a bunch of errors reported based on code that
> PHPUnit was
> executing! In this case, I discovered that:
>
> - PHPUnit passes a boolean false to `debug_backtrace()`... which is
> documented
>   as expecting an integer! (There are actually several constant values it
>   accepts, all of which are integer values.) In this case, PHPUnit is
> relying
>   on the fact that the engine casts booleans to the integers 0 and 1.
> (Zeev has
>   written to the list already indicating that this coercion path will be
>   supported in the patch.)
> - PHPUnit is passing the results of $reflector->getDocComment() blindly to
>   substr() and preg_match*(). getDocComment() is documented as returning
> EITHER
>   a string OR boolean false. Again, PHPUnit is relying on PHP to cast
> boolean
>   false to an empty string. (Zeev has also indicated this coercion path
> may be
>   re-introduced.)
>
> I was able to fix these in a matter of minutes, and then my tests ran, and
> passed without any changes.
>
> #### Analysis
>
> STHcoerce worked about how I expect STHv5 will work _if_ _every_ _file_
> were
> declared in strict_types mode. In other words, it uncovered errors in
> calling
> both userland and internal functions. Userland typehints worked as I
> expected,
> with floats using fractional values not casting to integers.
>
> ### Wrap Up
>
> STHcoerce was actually far more strict than I found strict_types mode to
> be in
> STHv5. The reason is that it's a single, non-optional mode. This poses a
> potential challenge to migration, as noted in my problems using PHPUnit
> (Yes, I
> WILL be sending patches their way soon!): method calls and arguments that
> previously worked because of how PHP juggles types often do not work,
> particularly when going from boolean to other scalar values. However, the
> patch
> does what I'd expect in terms of preventing operations that would result in
> either data loss or data additions, all of which can have unexpected side
> effects if you don't understand the casting rules currently.
>
> The flip side to this is that you do not need to make any changes to your
> code
> in order to locate and fix errors. What this means from a library/framework
> author perspective is that, if the STHcoerce patch is merged, I can test
> against
> PHP 7, make fixes, and my code is not only forward-compatible, but also
> backwards to the various PHP 5 versions I might already be supporting —
> and that
> code now benefits from being more correct.
>
> Because STHv5 is opt-in only, the only way to see similar type errors is to
> somehow automate the addition of the strict_types declaration to all files
> in
> your project. While it can be done with tools like sed and awk,
> realistically it
> means that existing libraries cannot and/or will not benefit easily from
> the
> changes until they support PHP 7 as a minimum version. Additionally, it
> poses
> potential problems in terms of different testing results based on which
> mode you
> run in, leading to ambiguity for users. The only way to address the latter
> as a
> library author is to specify which mode your code is known to run in.
>
> Ironically, I'm seeing STHcoerce as more strict than STHv5 in terms of type
> handling, due to the fact that every call, userland or internal, is
> affected.
> The fact that it's always on makes it simpler for me to test against it
> now, and
> makes it easier to make my existing code both forward-compatible and more
> correct — even if I do not add type hints until I update my minimum
> supported
> version to PHP 7.
>
> I am slightly worried about the amount of work needed to make code run
> from v5
> to v7 if STHcoerce is adopted. That said, the issues I found in PHPUnit
> were
> corrected in minutes (though a more thorough patch that allows early
> return from
> methods if doc comments are not strings would be better), and my own
> library's
> tests ran without problems once the PHPUnit issues were corrected (both
> code
> with and without typehints). Strict_types is definitely interesting, but I
> found
> that strict_types mode was more or less how I wanted code to operate, and
> to
> opt-in to that means changes to every file in my library — which is a much
> larger migration problem.
>
> In the end: kudos to everyone who is working on these patches and RFCs. I'm
> excited about scalar type hints in PHP 7!
>
>
> --
> Matthew Weier O'Phinney
> Principal Engineer
> Project Lead, Zend Framework and Apigility
> matt...@zend.com
> http://framework.zend.com
> http://apigility.org
> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>

Reply via email to