On 02/16/2015 09:48 PM, Sara Golemon wrote: > Second, I should clarify that while the HHVM runtime performs > coersion, the hack type checker is strict. So my original statement > was inaccurate. As far as hack is concerned, it's simply strict. > Period.
With both the default (partial) type checking and strict enabled, my number_format() example in Hack produces: int(1000) 1,000 string(4) "1000" 1,000 float(1000) 1,000 string(5) "1000 " Warning: number_format() expects parameter 1 to be double, string given string(5) " 1000" 1,000 string(9) "1000 dogs" Warning: number_format() expects parameter 1 to be double, string given string(3) "dog" Warning: number_format() expects parameter 1 to be double, string given resource(4) of type (stream) Warning: number_format() expects parameter 1 to be double, resource given Basically it accepts, ints, floats and well-formed numeric strings and the hh_client type checker is telling me I have "No errors". So the only difference between Hack's strict mode and the current coercive behaviour in PHP is strings with trailing chars. The "1000 dogs" case. "1000 " as well in my example, but that is the same case. Where in PHP you get a notice but it still does the conversion and in Hack you get a warning and the conversion isn't done. So even though Hack has both a "partial" type checking mode and a "strict" mode, the decision was to still do type coercion for the others. I kind of expected it to only accept a float in full-on strict mode to mimic the no-compromise strictness proposed in the RFC. Also, looking through the code, I really don't see this "simply strict" anywhere when it comes to calling internal functions. For example: $a = [1,2,3,4,5]; print_r(array_reverse($a,"0")); It doesn't complain that "0" is a string and not a boolean. It doesn't even complain about "dog" there. And the one everyone gets uppity about. bool->int conversion in curl_setopt(). eg. $ch = curl_init("https://74.125.28.104"); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch); echo curl_error($ch); PHP obviously converts true to 1 there which has been a problem because what people really meant was to set it to 2. We spew a notice for this, of course: Notice: curl_setopt(): CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl 7.28.1. It is recommended to use value 2 instead in ... In Hack it appears that true is also converted to 1 in <?hh // strict mode and no notice appears and the hh_client type checker doesn't complain. If instead of true I pass in an array of strings, it still converts it to 1 even though the type is blatantly wrong. It looks like it was kept quite loose to match PHP and not cause too much legacy code to break. In this particular case it is pretty dangerous to be completely silent about it though since it actually means no host verification is getting done. The output when properly set to 2 from both PHP and Hack is: SSL: certificate subject name 'www.google.com' does not match target host name '74.125.28.104' Please correct me here if I somehow ran these incorrectly. I did put some deliberate type errors into my userspace code and hh_client caught those nicely, so it seems like it was working, but it didn't catch anything when it came to calling the internal API functions. eg. <?hh // strict function test() : int { $ch = curl_init("https://74.125.28.104"); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, ["I have no idea what I am doing"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch); echo curl_error($ch); return "beer"; } hh_client reports: /home/rasmus/test/a.php:8:12,17: Invalid return type (Typing[4110]) /home/rasmus/test/a.php:2:19,21: This is an int /home/rasmus/test/a.php:8:12,17: It is incompatible with a string When I change return "beer" to return 1 hh_client is happy. So, you keep asking what I would support. I would like to see an RFC along the following lines: 1. Tighten up the type coercion for the "1000 dogs" case although we have to look at whether there is a problem with some database APIs returning space-padded fields so "1000 " would now break. Hopefully that is fringe enough to not break the world. 2a. In strict mode, tone down the strictness and allow non-lossy coercion including int->float. And yes, I know in really edge cases that isn't technically non-lossy, but for all practical purposes it is. or 2b. A much more flexible system for specifying multiple types. I should be able to say that my function takes something that looks like a number if I choose and still take advantage of stricter typing for other parameters. 3. Don't turn on crazy-strict mode for internal functions that weren't designed for that. Instead provide the same ability as userspace gets for developers to gradually design their APIs to be stricter if they so desire allowing both Hack and PHP to implement a stricter curl_setopt(), for example. -Rasmus
signature.asc
Description: OpenPGP digital signature