Re: [RFC] Context Managers

From: Date: Mon, 10 Nov 2025 07:13:27 +0000
Subject: Re: [RFC] Context Managers
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-129187@lists.php.net to get a copy of this message
Hello all. > It makes it very easy to not call the exitContext() method when calling > enterContext() manually Consider the code below: ```php class FileContext { private $handle; public function __construct(private string $filename, private string $mode) {} public function __enter() { $this->handle = fopen($this->filename, $this->mode); return $this->handle; } public function __exit(?Throwable $e = null) { if ($this->handle) { fclose($this->handle); } } } $ctx = new FileContext('example.txt', 'w'); $f = $ctx->__enter(); try { fwrite($f, "Hello world"); } finally { $ctx->__exit(); } ``` Question: what is the probability of making a mistake in this code? What is the likelihood that a programmer will forget to call enter and exit? ```php ... with (new FileContext('example.txt', 'w')) as $f { fwrite($f, "Hello world"); } ``` In this case, the probability of forgetting to call enter or exit is zero, since the language now supports this paradigm at the syntax level. Question: what is the probability of accidentally calling a method instead of not calling it? ```php ... with (new FileContext('example.txt', 'w')) as $f { $f->__enter(); // Error! fwrite($f, "Hello world"); } ``` I believe that finding a clear mathematical proof in this case is impossible. But if we look at studies on error statistics, it is the absence of a call that is the most common problem. (https://tomgu1991.github.io/assets/files/19compsac.pdf) > Thus, we have a big pitfall, wherein APIs may expect enterContext() and exitContext() Is it really a big pitfall? If so, then functions like fopen and fclose should be removed from the language altogether, because their existence is an even bigger pitfall. > Ultimately you definitely will need the capability of calling enterContext() and exitContext() > manually too (i.e. restricting that is not realistic either) Of course, they can be restricted: make the methods private, so that only PHP itself can call them, and they cannot be accidentally called anywhere else outside the class. But I don't see any convincing reasons for doing that. > The proposed approach only allows nesting contexts, but not interleaving them. Why does this need to be done at all? I don't know what "interleaving contexts" means in practice. But even if they do exist, that goes beyond the scope of the current proposal. Nevertheless, it is worth noting that studying Python bugs for this RFC is a good thing: https://bugs.python.org/issue29988 - with statements are not ensuring that __exit__ is called if __enter__ succeeds. Also: https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager Total: **Advantages of with:** * better semantics than try–catch * less control-flow code It would be strange to demand that with be safer than the rest of PHP code. That’s an odd requirement. Of course, if PHP were a compiled language, many checks could be done at compile time. But we have static analysis for that. --- Best regards, Ed

« previous php.internals (#129187) next »