Re: [RFC] Auto-capture multi-line closures and shortfunctions take 2

From: Date: Sun, 28 Mar 2021 02:49:11 +0000
Subject: Re: [RFC] Auto-capture multi-line closures and shortfunctions take 2
References: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  Groups: php.internals 
Request: Send a blank email to internals+get-113820@lists.php.net to get a copy of this message
> On Mar 27, 2021, at 12:05 PM, Rowan Tommins <rowan.collins@gmail.com> wrote:
> 
> On 27/03/2021 00:05, Nuno Maduro wrote:
>> 
>> I've just added a few more tests with the exact examples you have presented in this
>> mail list: https://github.com/php/php-src/pull/6246/commits/c3a50d671c5d8fa4b775ec67fe77d0cbd5cc8030
>> <https://github.com/php/php-src/pull/6246/commits/c3a50d671c5d8fa4b775ec67fe77d0cbd5cc8030>.
> 
> 
> Hi Nuno,
> 
> Thanks, I hadn't thought of writing out test cases, that makes a lot of sense; although I
> now realise my question wasn't very clear.
> 
> My biggest concern with automatic capture is the potential for *accidentally* capturing
> variables - that is, intending to introduce a local variable inside the closure, but capturing a
> variable from the outer scope that happens to have the same name. This is less of an issue with
> capture by value, but can still mean resources not being freed, e.g. a large array of data not being
> freed from memory, or an object destructor not executing when expected.
> 
> This is more likely in PHP than many other languages, because there is no requirement, or even
> an option, to explicitly declare a local variable in the closure. It's not a new problem, but
> since single-expression closures are unlikely to use many local variables, it's probably not
> one that's been given lots of thought.
> 
> 
> I've written some tests that demonstrate the current behaviour using an object destructor:
> https://github.com/nunomaduro/php-src/commit/ae18662cc92f5d07520b4574dcae71d38a9e0a41
> 
> Based on those, there seems to be no way to prevent a variable being captured, even if its
> value is immediately discarded each time the closure runs. This may be less than ideal:
> 
> $results = getLargeReportFromDatabase();
> // ...
> $fn = fn() {
>     $results = []; // coincidentally the same name, immediately assigned its own value
>     // ...
> }
> unset($results); // does not free the array, because $fn has captured the value

In this case doesn't $results get released when $fn goes out of scope?  

IOW, if fn() is used and discarded by the end of the function in which is it declared then this
accidental capture is not an issue (unless it breaks the outer code, of course), right?

If it breaks in the outer code then I would say that is not really any different than overwriting
the variable in a later loop, for example. So not really an indictment of auto-capture.

It is only if the function allows the closure to live on by returned it directly or indirectly,
assigning it to a by-reference parameter or assigning to a property of an object that was passed in
that it can "leak."

Which then begs the question of "How often do closure get returned in a manner they have a long
life AND a large number of the same types of closures are created?  I can envision how that might
happen, but I question how common that scenario would be?

And finally, most to the time a PHP page terminates after a page load thus releasing all these
captured variables.  Yes CLI apps and "Fiber" apps might be different, but they are
certainly less common than request/response web pages.

IOW, it feels like there would need be a confluence of many factors that collectively are likely
rare before this scenario could become a real problem. 

Where one solution would be, of course, to not write long functions such that it is hard to identify
accidentally captured variables. Which seems like a best practice anyway?

Did I get anything wrong above? I don't think so but then I could well have missed something.

In summary, is this accidental-capture-which-turns-into-a-resource-leak actually a problem worth
worrying about?


> I wonder if the capture analysis could be made smarter to make this less likely.
> 
> 
> PS I'd like to apologise if some of my messages in this thread have come across as harsh
> or demanding, I do appreciate you bringing up this feature, as I know it's one a lot of people
> want, even if I'm sceptical.
> 
> Regards,
> 
> -- 
> Rowan Tommins
> [IMSoP]
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 


Thread (76 messages)

« previous php.internals (#113820) next »