Re: [RFC] Context Managers, v2
| From: | Daniel Scherzer | Date: | Fri, 13 Nov 2026 23:53:15 +0000 |
| Subject: | Re: [RFC] Context Managers, v2 | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-133100@lists.php.net to get a copy of this message | ||
Hi Larry,
On Fri, Nov 13, 2026 at 3:21 PM Larry Garfield <larry@garfieldtech.com>
wrote:
> Hi folks. Based on the feedback and problems with the previous Context
> Managers RFC, Arnaud and I have a new approach to present:
>
> https://wiki.php.net/rfc/context-managers-v2
>
> It basically swaps the two-method approach in favor of "it's a generator,
> you're welcome." The result is, I think, both simpler and more flexible,
> and resolves a number of other issues as well. More details in the RFC.
>
> There is a linked implementation, though Arnaud warns it's only partially
> complete so go easy on it. :-) But the design in the RFC is all ready for
> review.
>
> --
> Larry Garfield
> larry@garfieldtech.com
Some feedback on the current RFC draft
1. The behavior section says
> When a using expression is encountered, the GENERATOR is first evaluated
to
> ensure it is a Generator object. If it is not, an Error is thrown. (See
the
> section below regarding resources, however.)
Can you include some mention of
ContextManager here, since GENERATOR can
be
evaluated to a ContextManager that is then called to get the generator.
2. I'm wondering about what happens if the generator throws an exception.
Specifically, it could throw after yielding, but before it terminates, i.e.
when it resumes execution after the BODY finishes, returns, or throws.
Looking at the "Implementation details" example desugaring, it seems like
that
exception would just be silently ignored, but I don't see that anywhere in
the
specification.
3. A number of other things trigger errors, but for generators that yield
with
keys, the keys are just silently ignored - did you consider throwing an
error
for that too?
4. I'd prefer to not add special syntax for this in try-catch, it looks
like it
just saves 3 characters (opening {, closing };) plus any whitespace that
the developer wants, and it looks a bit odd to me. We can always add this
later
if it becomes a common pattern. It also means that the returned value from
the
using block cannot be stored anywhere.
5. Speaking of the returned value from the using block, can you confirm that
NoDiscard will be handled properly? Consider a modified version of the
file_for_writing function given as an example:
```php
/** Returns true if everything succeeded, and false otherwise */
#[\NoDiscard('as failures should be handled')]
function file_for_write(string $file)
{
$fp = fopen($file, 'w');
if ($fp) {
try {
yield $fp;
// If this line is reached, then the using didn't throw an
exception
return true;
} catch (\Exception $e) {
log('The file failed.');
} finally {
fclose($fp);
}
}
// Either fopen() didn't succeed, or it succeeded but the using
block
// had an exception.
return false;
}
```
for the example
```php
using (file_for_write('file.txt') => $fp) {
foreach ($someThing as $value) {
fwrite($fp, serialize($value));
}
};
```
the returned value from file_for_write isn't used and should trigger a
warning.
6. Is there a way for the generator to specify that the *yielded value*
should
not be discarded? The current RFC text says
> If no VAR is specified, the yielded value is ignored.
and while NoDiscard would highlight the ignoring for a function return, it
doesn't for generator yields.
Thanks,
-Daniel