On Sat, Nov 15, 2025, at 18:22, Edmond Dantes wrote: > > To provide an explicit example for this, code that fits this pattern is > > going to be problematic > > Why is this considered a problem if this behavior is part of the > language’s contract? > Exactly the same way as in Go for example, this is also part of the > contract between the language and the programmer.
One of the stated goals of the RFC: *Code that was originally written and intended to run outside of a Coroutine must work EXACTLY THE SAME inside a Coroutine without modifications.* The examples you give here seem to contradict that. You are now saying that developers *must* refactor shared state, must avoid passing objects to multiple coroutines, and must adopt a certain programming style to avoid breaking existing code. That’s the opposite of "works exactly the same without modification". > > $this->data can be changed out from under writeData(), which leads to > > unexpected behavior. > > So the developer must intentionally create two different coroutines. > Intentionally pass them the same object. > Intentionally write this code. > And the behavior is called “unexpected”? :) The original claim of the RFC is that code *not written with coroutines in mind* should still behave the same inside them. If any function can suspend at arbitrary points, the ordinary synchronous assumptions, including read/modify/write patterns on properties, no longer hold. Whether that pattern is good style or not doesn’t change the fact that the behaviour is different once asynchrony is introduced. > A developer must understand that potentially any function can > interrupt execution. This is a consequence of transparent asynchrony. This is also a direct tension with another major goal: *A PHP developer should not have to think about how Coroutine switch and should not need to manage their switching—except in special cases where they consciously choose to intervene in this logic.* If any function can suspend, then developers MUST reason about all the usual concurrency hazards: torn writes, interleaving, race conditions, and the entire class of bugs that coloured function models prevent. That absolutely counts as "thinking about coroutine switching". > It is both its strength and its weakness. I will repeat it again: not > some specific function, but almost ANY function. Because under > transparent asynchrony you can use suspend() inside any function. This > does not negate the fact that documentation should list all functions > that switch context, but a certain coding style encourages this way of > thinking. These statements also seem to go against another goal of the RFC: *A PHP developer should not have to think about how Coroutine switch and should not need to manage their switching—except in special cases where they consciously choose to intervene in this logic.* > How did we refactor old code for coroutines? > > 1. We took the modules that had global state. There were not many of them. > 2. We used a Context, which is essential, and moved the global state > into the context. > [snip] > But why anyone would intentionally pass the same object to different > coroutines and then complain that the code broke. I have no idea who > would need that. :) Existing PHP codes does this today without issue. Many libraries, parsers, database clients, stream decorators, in-memory caches, DTOs, middleware chains ... are built around shared mutable objects. That style is extremely common in PHP, and today it’s perfectly fine to share these things. Saying "just refactor all your shared-state-code" seems to contradict the goals given in the RFC. > A developer should strive to minimize asynchronous code in a project. > The less of it there is, the better. Asynchronous code is evil. An > anti-pattern. A high-complexity zone. But if a developer chooses to > use asynchronous code, they shouldn’t act like they’re three years old > and seeing a computer for the first time. Definitely not. This > technology requires steady, capable hands :) > > Best Regards, Ed. Right now, today, PHP has almost zero async code in the ecosystem. If the position of the RFC is that transparent asynchrony is inherently dangerous, requires careful discipline, breaks common patterns, and requires refactoring shared state, then it isn’t clear how the central value proposition "existing code works unchanged" is meant to hold. This is why the semantics need to be written down explicitly, not left to implication or the experience of those who already work with coroutines. — Rob
