Re: PHP True Async RFC Stage 4

From: Date: Thu, 16 Oct 2025 11:31:21 +0000
Subject: Re: PHP True Async RFC Stage 4
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-128853@lists.php.net to get a copy of this message
On Thu, Oct 16, 2025, at 09:38, Daniil Gentili wrote: > > > You've provided examples and said that it violates design and fundamental elements, > > but not which design and fundamentals, ie, the evidence for the decision. I would expect more than > > "because I said so" for such a huge language feature, but rather arguments grounded in > > computer science. > > > He very explicitly described the issue, in objective terms: a breach of agreement in the > context of the invocation of a foreign interface. > > In simpler terms, you can't and should not be able to mess with the internals of code you > didn't write: this is similar to the principle of encapsulation in OOP, where you cannot modify > private properties of an object. > > > Cancellation should be part of the contract of an async function: it is safe, and most async > languages already implement it explicitly by passing a context or a cancellation token, the current > approach of the RFC does it implicitly, which is also fine. > > Awaiting for the completion of spawned coroutines should *not* be part of the contract of an > async function: it is an incredibly easy footgun, as it's incredibly easy to spawn a coroutine > meant to i.e. run until the object is destroyed, and then encounter a deadlock when the linked scope > is awaited for before the object is destroyed (even messier if cycles and thus the GC are involved). > > Languages like Kotlin that do implement await on scopes have already realized that it is a > mistake, as can be seen by the many warnings against using await on a scope, as I already linked in > previous emails. > > On the other hand, making the same mistake described above, by cancelling a scope, will produce > a very easy to debug exception instead of a deadlock, easily fixable by (warning the author of the > library class) to use a new scope to spawn coroutines within the object. > > Awaiting a scope leads to deadlocks in case where a separate scope is needed but not used, > cancelling them leads to a simple exception. > Awaiting on multiple tasks can already be done, explicitly, with TaskGroup. > > > Regards, > Daniil Gentili. Hey Daniil and Edmond, I think I understand the intention. Would it be better to instead of having ->awaitCompletion (which feels like an implicit implementation of Awaitable without an explicit implmentation -- which is the part that was bothering me), maybe having something like ->joinAll() or ->joinOnCancellation()? That way someone like me won't come along and wrap them in an Awaitable because it looks Awaitable. It also might be a good idea to make specifying a timeout in ms mandatory, instead of a taking an Awaitable/Cancellation. This would also prevent people from simply passing a "never returning" Awaitable thinking they're being clever. It also might be good to provide a realistic looking example showing a "bad case" of how this is dangerous instead of simply saying that it is, showing how a scope is not a 'future', but a container, and preemptively mention TaskGroups, linking to the future scope (which it should also probably be listed there as well). — Rob

« previous php.internals (#128853) next »