Pavel, On May 16, 2020, at 05:13, Pavel Patapau <algerd....@gmail.com> wrote: > > Hello everyone, > > I want to propose new syntax addition - guard statement, that executes code > only if expression equals false and must contain control-flow changing code, > and written a respective RFC: > > https://wiki.php.net/rfc/guard_statement > <https://wiki.php.net/rfc/unbundle_xmlprc> > > Implementation in progress. > > I started work before this proposal https://externals.io/message/110107 and > respected some moments in the RFC. > > > Thanks for consideration, > Pavel
Regarding this part of the proposal: > Body of statement must contain code that changes control flow: return, throw, > goto. Also, in a loop context, you can use break or continue. > > If compiler doesn't find any of those statements, it will search selection > type statements(if with else|try/catch/finally|switch) and ensures that every > element of these statements contains return, throw, goto. I feel that from an implementation standpoint, this could be fairly complex, especially since code such as: guard (COND) else exit; guard (COND) else call_some_function_that_calls_exit(); ought to compile without warnings. (Exit was explicitly included in my original proposal on the mailing list.) Some languages allow this by marking functions with a noreturn attribute (C, Swift < 3). Swift >= 3 solves this problem by having a "Never" return type, which is validated by Swift's type checker, requiring all code paths to also call another function returning Never. (As an implementation detail, Never is an enum with no cases.) Otherwise, you would have to write guard (COND) else { exit; return; } to satisfy the parser, which is silly. I would suggest an alternative that is conceptually simpler and allows for this use case. We can observe that if we slightly loosen the restriction that the _compiler_ must be able to do a full call path analysis, a guard statement can also be thought of as: guard (COND) else { STATEMENTS; throw new \GuardFailureError; } That is, the else clause ends with a compiler-generated fatal error. This means the compiler itself doesn't _have_ to do a full analysis of every call path in the STATEMENTS to ensure proper exit; the runtime can trap as well. This allows us to be a bit more flexible: if the compiler can prove one way or the other, it can either fail compilation, or else omit generating the opcodes for throwing the GuardFailureError. But code that the compiler _can't_ prove (such as the previously mentioned code-that-calls-exit) should still be allowed. If we later add language support for a noreturn attribute, or some other mechanism to account for that, then we are in a position to allow for that complexity in the parser and remove the runtime handling. It would obviously be preferable if the compiler can catch errors in all cases, but when it can't (and php's dynamicity makes this a hard problem), I think it's acceptable that the runtime can serve as a fallback. -John -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php