On Mon, Feb 16, 2015 at 4:52 PM, Rasmus Lerdorf <ras...@lerdorf.com> wrote:
> On 02/16/2015 03:58 PM, Sara Golemon wrote:
>> On Mon, Feb 16, 2015 at 2:50 PM, François Laupretre <franc...@php.net> wrote:
>>> Once again, anyone can take over version 0.3, if it is so great. Why don't 
>>> you do it ?
>>> I will play the game, stop working on my proposal, and vote 'yes' again.
>>> But don't ask me to do it in your place.
>>>
>> If nobody else does it, I will.
>>
>> I think Andrea's 0.3 proposal was extremely well balanced, served
>> everyone's needs whether they would admit it or not, and who's only
>> failing (subjectively termed) was the use of declare().  I think
>> declare() is fine and not nearly as ugly as some have slandered it to
>> be, but I'm willing to read the winds and modify it for v0.4.
>
> I still disagree strongly that it serves everyone's needs. The internal
> API and APIs provided by extensions are completely messed up by this
> approach. Userspace authors get the choice when they write their code.
> Even if the caller has turned on strict, if you haven't added strict
> types to your functions/methods you are fine. Internal API and extension
> authors don't get this luxury. If the caller turns on strict, then
> suddenly an API that was written explicitly to make use of the coercive
> characteristics PHP has had for 20+ years breaks and there is nothing I
> can do about it as an extension author. This is beyond just int->float
> coercion, which is, of course, also missing.
>
> A simple example:
>
> number_format($num);
>
> So, for various inputs without strict enabled:
>
> int(1000)
> 1,000
>
> string(4) "1000"
> 1,000
>
> float(1000)
> 1,000
>
> string(5) "1000 "
> Notice: A non well formed numeric value encountered in ...
> 1,000
>
> string(5) " 1000"
> 1,000
>
> string(9) "1000 dogs"
> Notice: A non well formed numeric value encountered in ...
> 1,000
>
> string(3) "dog"
> Warning: number_format() expects parameter 1 to be float, string given
> NULL
>
> resource(5) of type (stream)
> Warning: number_format() expects parameter 1 to be float, resource given
> NULL
>
> This is the intended API. The function does some sanity checking for
> things that clearly don't make sense based on what it was written to do
> and fails hard. It also lets the user know about questionable data and
> relies on coercion for the rest. You could argue that the "1000 dogs"
> case should be more severe than a notice, but that is pretty minor I
> think. The extension author has the ability to make that more severe if
> she likes.
>
>
> Now turn on strict and we get:
>
> int(1000)
> number_format() expects parameter 1 to be float, integer given
>
> string(4) "1000"
> number_format() expects parameter 1 to be float, string given
>
> float(1000)
> 1,000
>
> string(5) "1000 "
> number_format() expects parameter 1 to be float, string given
>
> string(5) " 1000"
> number_format() expects parameter 1 to be float, string given
>
> string(9) "1000 dogs"
> number_format() expects parameter 1 to be float, string given
>
> string(3) "dog"
> number_format() expects parameter 1 to be float, string given
>
> resource(5) of type (stream)
> number_format() expects parameter 1 to be float, resource given
>
> That in itself might not be so terrible, but also not terribly useful
> and it is nothing like what the extension author had intended. And how
> do you think users will deal with internal functions that are now
> suddenly strongly typed even though they were not designed to be? Do you
> think they will go look at the source code for the function and mimic
> the data sanity checks and put those in their userspace code? Doubtful,
> and as people on irc and everywhere have told me, they will just cast.
> No big deal. So, we run the same set of data through with strict enabled
> and doing a number_format((float)$num):
>
> int(1000)
> 1,000
>
> string(4) "1000"
> 1,000
>
> float(1000)
> 1,000
>
> string(5) "1000 "
> 1,000
>
> string(5) " 1000"
> 1,000
>
> string(9) "1000 dogs"
> 1,000
>
> string(3) "dog"
> 0
>
> resource(5) of type (stream)
> 5
>
>
> Out of the 3 scenarios, this is inarguably the worst outcome with the
> last line there being the most blatant. Actually outputting an internal
> resource id as if it was a valid number to be formatted without the
> slightest notice or warning anywhere that something is wrong in the code.
>
> This is my fear with this approach. People will start littering their
> code with casts and it will hide real bugs which is the complete
> opposite of what motivated this in the first place.
>
> Without more thought into how we properly deal with internal/extension
> code I don't really understand how so many people foresee this to work
> perfectly in the real world.
>
> -Rasmus
>

I think you bring up a good point, Rasmus. Extension implementations
have existed for many years in a world before user-land scalar
typehints. I can see how the author of an extension might have
written their code in a way that relies on assumptions about how
argument coercion behaves.

What would you say if zend_parse_parameters() API and friends were
left alone, and a new flag or new versions of these APIs were
introduced so that extension authors could gradually adopt the new
parameter checking/coercion scheme at their leisure?

When adopting the new parameter checking/coercion scheme, if an
author needs/wants to do something different for parameter checking
or coercion for a given extension, it occurred to me that they could
just omit the typehint (i.e. use "z" for zend_parse_parameters())
and then do manual checking inside the function's body. I've seen
this technique used in a number of extensions (and in pure PHP
functions) and it doesn't seem to cause significant problems AFAICT.

I know this isn't a fully baked solution to the issue you raise, but
I'm curious to hear your thoughts about this approach.

Regards,
Drew Paroski

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to