>
> If you await a value, everything works, but then someone somewhere else
> awaits the same Awaitable that wasn't actually a "one-shot" Awaitable,
> so now everything breaks sometimes, and other times not -- depending on which
> one awaits first.
>
There is a function:
```php
function my(mixed $i)
{
return $x + 5;
}
```
Someone called it like this somewhere: my("string"), and the code broke.
The question is: what should be done?
Do we really have to get rid of the mixed type just to prevent someone
from breaking something?
If a programmer explicitly violates the contracts in the code and then
blames the programming language for it. So the programmer is the one
at fault.
If someone uses a contract that promises non-idempotent behavior, it’s
logical to rely on that.
> 2. memoization becomes an issue
The same question: why should the code work correctly if the
agreements are violated at the contract level?
There’s no element of randomness here.
1. A person deliberately found the Awaitable interface and inserted it
into the code.
2. They deliberately wrote that function.
So what exactly is the problem with the interface itself?
> With a "multi-shot" Awaitable, this is not practical or even a good idea. You
> can't write general-purpose helpers, at all.
In what way are generalized types a problem?
Why not just use the contracts correctly?
```php
function getOnce(Awaitable $some) {
if($some instanceof FutureLike === false) {
return await($some);
}
static $cache = [];
$id = spl_object_id($some);
return $cache[$id] ??= await($some);
}
```
> 3. static analysis
I really don’t see how static analysis could help here. What exactly
would it be checking?
> 4. violation of algebraic laws with awaitAll/awaitAny
And the fact that awaitAll/awaitAny are designed to correctly handle
Awaitable objects?
I’m not aware of any such violations.
> 5. violation of own invariants in the RFC
Can you show which statement of the RFC is being violated here?
What invariants?
> 6. common patterns aren't guaranteed anymore
So JavaScript yes?
```js
class NonIdempotentThenable {
constructor() {
this.count = 0;
}
then(resolve, reject) {
this.count++;
resolve(this.count);
}
}
async function demo() {
const obj = new NonIdempotentThenable();
console.log(await obj); // 1
console.log(await obj); // 2
console.log(await obj); // 3
if (await obj) {
console.log(await obj); // 5
}
}
demo();
````
Other cases generally have the same problem — a violation of the agreement.