You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
never return type for arrow functions with throw expressions #7900
The general problem is that return <expr> is forbidden at compile-time (which the short closure expands to). Now, if we loosen this restriction, we have to completely get rid of the compile-time check, for short closures, and just check at runtime. (We cannot just see throw, because calling another function returning never is equally valid.)
Reacted by Christoph M. Becker, Ilija Tovilo and orklah
We could of course not add that implicit return for never. In that case the arrow function would simplify throw if the end of the function is reached without throwing/exiting, just like normal never functions do. I wouldn't classify this as a bug though.
Yes, theoretically we could do the same here, although it's more controversial. E.g.
// Makes sense, inner function returns `void` (`NULL`), outer function returns `void` toofn (): void => voidFn()
// Makes sense, inner function might have desired side effects but result is not neededfn (): void => nonVoidFn()
// Not useful, any side-effect free expression that has no purpose is discardedfn (): void => 42
That said, this change would at least require a mail to the mailing list and likely an RFC as historically there have been quite a few disagreements with how void/never should behave.
The void case is definitely weird indeed. There is no way to generate a "void" value without a return; or ending a function without statement. Both of those solutions can't be used here because the return is implicit and an arrow function must have a statement. This is the kind of situation where a null pseudo type would be useful though...
But dropping the implicit return implies that it would need to be added by users, no? Otherwise PHP would need looking at the return type in signature to decide if the statement value must be returned or not? It seems icky
Otherwise PHP would need looking at the return type in signature to decide if the statement value must be returned or not? It seems icky
Yes, PHP could add the return depending on whether the function is void/never or not. FWIW other languages do the same. E.g. for Swift this was a problem in the past but they now just drop the value when the closure is explicitly marked as returning ().
Yes, PHP could add the return depending on whether the function is void/never or not.
This should only be necessary if the arrow function body solely contains a method/function call, doesn't it? So a literal value would always require a return statement and would (rightly so) cause a fatal error given a different return type.
Activity
weirdan commentedon Jan 7, 2022
/cc: @muglug & @ondrejmirtes (authors of the RFC that introduced
never).ondrejmirtes commentedon Jan 7, 2022
Funny - both PHPStan (https://phpstan.org/r/a18b627c-e478-4091-ab28-429523eece5e) and Psalm (https://psalm.dev/r/88e0288cfd) also report this wrong :)
Unfortunately I don't have the skillset to fix this but I agree this is a PHP bug: https://3v4l.org/MOKDU
weirdan commentedon Jan 7, 2022
It's not exactly wrong as long as PHP doesn't support it.
ondrejmirtes commentedon Jan 7, 2022
Also true 😊
bwoebi commentedon Jan 7, 2022
The general problem is that
return <expr>is forbidden at compile-time (which the short closure expands to). Now, if we loosen this restriction, we have to completely get rid of the compile-time check, for short closures, and just check at runtime. (We cannot just seethrow, because calling another function returning never is equally valid.)ricardoboss commentedon Jan 7, 2022
Would this also apply to functions returning void? https://3v4l.org/YkVBg
iluuu1994 commentedon Jan 7, 2022
PHP adds an implicit
returnto arrow functions.php-src/Zend/zend_language_parser.y
Lines 1209 to 1215 in 266667c
We could of course not add that implicit return for
never. In that case the arrow function would simplify throw if the end of the function is reached without throwing/exiting, just like normalneverfunctions do. I wouldn't classify this as a bug though.Yes, theoretically we could do the same here, although it's more controversial. E.g.
That said, this change would at least require a mail to the mailing list and likely an RFC as historically there have been quite a few disagreements with how
void/nevershould behave.orklah commentedon Jan 7, 2022
The void case is definitely weird indeed. There is no way to generate a "void" value without a
return;or ending a function without statement. Both of those solutions can't be used here because the return is implicit and an arrow function must have a statement. This is the kind of situation where a null pseudo type would be useful though...iluuu1994 commentedon Jan 7, 2022
The absence of a
returnalso generates a "void" value. A normal arrow function essentially gets rewritten to this:It should be safe to drop the implicit
returnhere.The controversial part comes from the fact that now this would also be valid code:
42is a useless, but valid expression statement.orklah commentedon Jan 7, 2022
But dropping the implicit return implies that it would need to be added by users, no? Otherwise PHP would need looking at the return type in signature to decide if the statement value must be returned or not? It seems icky
iluuu1994 commentedon Jan 7, 2022
Yes, PHP could add the return depending on whether the function is
void/neveror not. FWIW other languages do the same. E.g. for Swift this was a problem in the past but they now just drop the value when the closure is explicitly marked as returning().Example:
http://online.swiftplayground.run/
ricardoboss commentedon Jan 7, 2022
This should only be necessary if the arrow function body solely contains a method/function call, doesn't it? So a literal value would always require a return statement and would (rightly so) cause a fatal error given a different return type.
iluuu1994 commentedon Jan 7, 2022
Other expressions can also have side effects. E.g.
I wouldn't complicate the matter even more and just do everything or nothing.
[DowngradePhp82] Add DowngradeArrowFunctionNeverReturnTypeRector (#399)