Hey Anthony, > -----Ursprüngliche Nachricht----- > Von: Anthony Ferrara [mailto:ircmax...@gmail.com] > Gesendet: Montag, 23. Februar 2015 15:28 > An: Robert Stoll > Cc: PHP internals > Betreff: Re: [PHP-DEV] JIT (was RE: [PHP-DEV] Coercive Scalar Type Hints RFC) > > Robert, > > > [Robert Stoll] > > Sure, "a" was just an example to illustrate the problem. I figured it would > > not be necessary to say that the value of $b can > be completely unknown by the static analyser -> could come from user input, > from a database, from unserialising code etc. > (but probably that is what you meant with "this isn't the general case" > below). > > > > Assuming statically that $a is int or $b is string is erroneous in this > > context. > > > > Another problem to illustrate that a top type or at least some form of > > union type is required: > > > > function foo($x, $y, $z){ > > $a = 1; > > if($x){ > > $a = "1"; > > } > > If($y > 10){ > > $a = []; > > } > > If($z->foo() < 100){ > > $a = new Exception(); > > } > > echo $a; > > return $a; > > } > > > > How do you want to type $a without using a union type? > > Actually, this case is reasonably easy to handle. There's a representation > called SSA (Static-Single-Assignment) that you > move code to prior to doing type analysis. Basically, at a really high level, > it would rewrite the code to this: > > function foo($x, $y, $z){ > $a = 1; > if($x){ > $a1 = "1"; > } > $a2 = Φ($a, $a1); > If($y > 10){ > $a3 = []; > } > $a4 = Φ($a2, $a3); > If($z->foo() < 100){ > $a5 = new Exception(); > } > $a6 = Φ($a4, $a5); > echo $a6; > return $a6; > } > > Where Φ is a function that chooses the value based on the branch of the graph > that entered it. > There are a few ways to implement it in practice, one would be to generate a > variant.
[Robert Stoll] I am aware of SSA but it does not enable you to by-pass union types (sure in certain cases as below but that is it). Maybe I got one of your email wrong (or did not consider the context enough) but I got the impression that you think union types would not be necessary in strict mode. But they are, due to the fact that PHP supports data polymorphism (even for variables). There are cases where SSA is not applicable at all. Consider the above code but use $this->a instead of $a. In the end $this->a will have the type mixed in your static analyser. But I see that you are well aware of it. Recki-CT seems to be a nice project btw. :) > But another would be to generate > different code paths. Considering that $a5 will be the result if $z->foo() < > 1000 no matter what the prior conditionals are, > you could invert the code to push that check first, making it: > > function foo($x, $y, $z) { > if ($z->foo() < 1000) { > $a = new Exception(); > echo $a; > return $a; > } > if ($y > 10) { > echo []; > return []; > } > if ($x) { > echo "1"; > return "1"; > } > echo 1; > return 1; > } > > That transform can be done by the compiler, and hence never need you to do > anything. We still compiled without variants, > and the analysis job wasn't that difficult. > > There will be cases of course where this won't work. And in those cases we > could either not compile, or generate a variant. > > However, I would like to point out something. If you added a return type, and > ran that code in strict mode, it would error. A > static analyzer can pick up that error and tell you about it. [Robert Stoll] How come? You mean because PHP does not offer the possibility of union types yet or why? Specifying a return type mixed would be perfectly legal here even in strict mode. > > So really, we're not talking about valid strict code here (tho the same > problem does exist inside strict bodies, and > techniques can be done here the same. [Robert Stoll] I get more and more the impression that you talk about strong typing here or a language which is statically typed instead of the strict mode as presented in your v0.5 RFC or the coercive RFC as in this discussion. Or is this discussion about dynamic vs. static and I missed it? > > For more info, check out: > https://github.com/google/recki-ct/blob/master/doc/5_phi_resolving.md > > >> > >> And hence know **at compile time** that's an error. > >> > >> This isn't the general case, but we can error in that case (from a > >> static analysis perspective at least) and say "this code is too dynamic". > >> In strict mode at least. > > > > [Robert Stoll] > > If you go and implement a more conservative type system than the actual > > dynamic type system of PHP well then... you > can do whatever you want of course. > > But if you do not just want to support just a limited set of PHP then you > > will need to include dynamic checks in many > places. Or do you think that is not true? > > I think with strict type declarations, the 'limitations' are far less than > you'd think. Yes, there will be cases (like variable > variables, > etc) where valid strict code won't be analyzable. But I haven't seen var-vars > in the wild in a while. So I think my assertion is > fair: the majority of *valid* strict-typed code will be analyzable. Where the > majority of coercive won't be. [Robert Stoll] I agree with your first sentence but only in the case that your "strict type declarations" include somehow polymorphic declarations as well. Otherwise I would need to object vehement. Consider the following: $b = 1 + 2; $a = [1] + [2]; If you would claim that + can only have one strict type (num -> num) for instance, then no! Strict-typed code in this sense is not able to analyse most valid strict-typed code. But I guess you used an unfavourable wording and hence I do not go into more arguments here. As for your second sentence. Analysable are both variants. The coercive one will just need more effort and computer power - maybe something which you consider to be not feasible. Fair enough, but the claim is wrong. It is really not a question about strict-typed or coercive. From a static analyser point of view it can still predict the types equally well (as I said with lot more effort) - it only gets more complicated for the developer of the static analyser since she has to take implicit conversions into account as well when resolving a function, an overload respectively, has to propagate the implicit conversions forward etc. It is more complicated but doable. Of course, the resulting type system is uglier (and complex) than a type system for a strict-typed version and way uglier than a strongly and strict typed version (e.g. Haskell's type system as paragon). I haven't seen variable variables in the wild for a while either. Yet, variable function calls are quite common and dynamic includes are part of almost all template system in know. So in the end it really matters what a static analyser wants to achieve (support all features or only a sub-feature) and if it wants to remain compatible with PHP without changing behaviour (even if only a subset is supported) Your comparisons with Recki-CT are only helpful to a certain degree (they are very helpful, do not get me wrong). Yet, Recki-CT does not have the same behaviour as PHP. Consider the following: function foo(int $x){} $a = 1; if($x){ //$x is always false $a = 1 / $y; } echo $a; foo($a); Is translated according to the docs of Recki-CT to the following after SSA (annotated with types) function foo(int $x){} double $a = 1.0 if($x){ // double $a1 = 1 / $y; } double $a2 = Φ($a1, $a); echo $a2; //will no longer be 1 but 1.0 if the if branch was not taken, behaviour was changed by the compiler foo($a2); //will result in an error of course Btw. How do you type echo in Recki-CT? I guess you use conversions here as well ;-) or are object with __toString() not supported any longer? > > Anthony > > -- > PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: > http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php