Re: [PRE-RFC] Deprecate returning from a finally block

From: Date: Sat, 20 Jun 2026 13:25:40 +0000
Subject: Re: [PRE-RFC] Deprecate returning from a finally block
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-131428@lists.php.net to get a copy of this message
Hey Osama, On 18.6.2026 23:49:11, Osama Aldemeery wrote:
Hi all, I'd like to gauge interest in deprecating return inside a finally block, before I request karma to propose it as a full RFC. A return inside a finally silently discards whatever the try/catch was doing...a pending exception or return value just disappears, with no error or notice. As far as I know, it's the only abrupt exit from a finally PHP leaves silent... break/continue/goto out of one are already compile errors, and a throw auto-chains the discarded exception as $previous. Only return destroys the in-flight state and says nothing. Looking into the history of finally I found that the author of the original RFC said he added it only because Java allowed it, even though he thought it made "no sense" https://externals.io/message/61670#61678 But Java itself warns about it (javac -Xlint:finally). I also found that it was the source of a few bugs: * https://bugs.php.net/bug.php?id=70228 * https://bugs.php.net/bug.php?id=72213 * https://github.com/php/php-src/issues/11028 To see what a change would actually cost, I implemented the deprecation <https://github.com/php/php-src/compare/master...aldemeery:php-src:deprecate-return-in-finally> and ran it over the top ~5000 Composer packages. And I found that it's rare...there were only 12 occurrences across 9 packages out of 4992. Of those, 3 look like genuine latent bugs the deprecation caught, and the rest look deliberate. Here's the list of the occurrences: 1. ibexa/admin-ui (swallows the exceptions its own docblock declares)
    <https://github.com/ibexa/admin-ui/blob/2322d54/src/bundle/Controller/ContentTypeController.php#L834>
2. shopware/core (eats thumbnail failures and still reports success)
    <https://github.com/shopware/core/blob/e8079a0/Content/Media/Thumbnail/ThumbnailService.php#L294>
3. amphp/http-server (drops exceptions when the stream is already
    gone)
    <https://github.com/amphp/http-server/blob/b306134/src/Driver/Http2Driver.php#L1322>
4. dvdoug/PHPCoord (deliberate...finally is the method's return)
    <https://github.com/dvdoug/PHPCoord/blob/ced02c4/src/Point/CompoundPoint.php#L131>
5. dvdoug/PHPCoord (again)
    <https://github.com/dvdoug/PHPCoord/blob/ced02c4/src/Point/GeocentricPoint.php#L148>
6. dvdoug/PHPCoord (again)
    <https://github.com/dvdoug/PHPCoord/blob/ced02c4/src/Point/GeographicPoint.php#L221>
7. dvdoug/PHPCoord (again)
    <https://github.com/dvdoug/PHPCoord/blob/ced02c4ad44aa4a558f69d53af4834a9d50ab2aa/src/Point/ProjectedPoint.php#L242-L247>
8. spatie/ray (delibrate...any failure just returns false)
    <https://github.com/spatie/ray/blob/2da2079/src/Client.php#L71>
9. cakephp/cakephp (catch consumed the exception...finally just
    returns array)
    <https://github.com/cakephp/cakephp/blob/eef91f28de119bee5536905244d2096f752f2920/src/Database/Query.php#L1748-L1755>
10. hyperf/http-server (catch consumed the exception...finally emits
    response)
    <https://github.com/hyperf/http-server/blob/80c52d4/src/Server.php#L140>
11. silverstripe/framework (catch consumed the mysqli error)
    <https://github.com/silverstripe/silverstripe-framework/blob/9c59c42/src/ORM/Connect/MySQLiConnector.php#L213>
12. symfony/flex (try can't actually throw)
    <https://github.com/symfony/flex/blob/4a6d98e/src/PackageResolver.php#L88>
My take here is that the language already handles the analogous cases (continue/break/goto/...etc) natively, so leaving return looks like an inconsistency. I lean toward deprecating it now with an eye to an error in a future major (following the steps of Tim's deprecate-return-from-constructor RFC <https://wiki.php.net/rfc/deprecate-return-value-from-construct>)...though I guess a plain warning would be fine too. The main thing is that it seems worth doing something about. Is there appetite for this? Thanks, Osama
I dislike this. Yes, it's a rare occurence. But it's used legitimately in most places you found. (as you say, only 3 places were genuine issues.) So, why do you want to remove this? What's the point? It has some proper usage sites. We do have well-defined behaviour for return in finally. It works properly (by now) - it's not like it's a frequent source of bugs - there were a couple ones when initially introduced 10+ years ago, and a single one more recent. Also, no, it's not inconsistent - goto, continue etc. break out of the finally block and continue the functions execution. A return stops function execution as well. These are two different considerations. Feels a lot like "let's try changing something for the sake of it". No thanks. Thanks, Bob

« previous php.internals (#131428) next »