Stas, >>> -- Can the code generated for a strict type hint can somehow be optimized > significantly better than the code generated for a dynamic/coercive type > hint. >> And me, who wrote an AOT compiler that does **exactly** this, claim > > Sorry, did exactly what? Here a bit more explanation would help.
Optimized statically typed PHP functions. Or more specifically function calls inside of compiled code are treated strictly (so trying to pass a float to an int typed function would error at compile time). The outer function call (from non-compiled PHP) is parsed using ZPP rules, but once it's inside it's strict. https://github.com/google/recki-ct/blob/master/doc/0_introduction.md https://github.com/google/recki-ct/blob/master/doc/2_basic_operation.md >> However, since test_strict() is compiled, there's no reason to >> dispatch back up to PHP functions for strict_foo(). In fact, that >> would be exceedingly slow. So instead, we'd compile strict_foo() as a >> C function, and do a native function call to it. Never having to check >> types because they are passed on the C stack. > > Doesn't that assume strict_foo() is always called with the right type of > arguments? What exactly ensures that it does in fact happen? Shouldn't > you have the type check _somewhere_ to be able to claim this happens? > test_foo() doesn't do any checks, so what ensures $x is of the right > type for C? And if the check is there, how is it better? Yes it does check the types, but at compile time. My AOT compiler backend has no concept of a "mixed" or ZVAL type. All types are determined at compile time, and in the very few cases it can't it will error. The type inference engine attempts to determine specifically using all available information (prior context, current context, future context) to determine what the type is. It does also detect type changes (via assignment) and is able to correctly generate code based on that as well. >> And note that this can only work with strict types since you can do >> the necessary type inference and reconstruction (both forward from a >> function call, and backwards before it). > > I don't get the backwards part - I think you claimed it last time we > discussed it but I haven't seen your answer explaining why it's OK to > just ignore cases when the variable is of the wrong type. Right now, it > looks like you claim that if somebody has a call strict_foo($x) and > strict_foo() accepts integers, that magically makes $x integer and you > can generate code everywhere (not only inside strict_foo but outside) > assuming $x is integer without actually needing a check. I don't see how > this can work. Ok, let's take another example: <?php declare(strict_types=1); function foo(int $int): int { return $int + 1; } function bar(int $something): int { $x = $something / 2; return foo($x); } ^^ In that case, without strict types, you'd have to generate code for both integer and float paths. With strict types, this code is invalid. You can tell because you know the function foo expects an integer. So you can infer that $x will have to have the type integer due to the future requirement. Which means the expression "$something / 2" must also be an integer. We know that's not the case, so we can raise an error here. At that point the developer has the choice to explicitly cast or put in a floor() or one of a number of options. The function "bar" itself didn't give us that information. We needed to use the type information from foo() to infer the type of $x prior to foo()'s call. Or more specifically, we inferred the only stable type that it could be. Which let us determine that $x's assignment was where the error was (since it wasn't a stable assignment). Without strict typing this code is always stable, but you still need to generate full type assertions in a compiled version of foo() and use ZVALs for $x, hence reducing the effect of the optimization significantly. Anthony -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php