On Tue, 4 Nov 2025 at 10:28, Edmond Dantes <[email protected]> wrote:
>
> Hello all!
>
> Thank you for the RFC, it has been missing for many years.
> If I understand correctly, are you proposing to call `unset` at the
> end of the block?
>
> I see that the **Future Scope** section mentions `Disposable`.
> But if your goal is to introduce behavior based on `Disposable`,
> wouldn’t that conflict with the logic of the current RFC?
> I see a clear pitfall here.
>
> If you accept this RFC with the `unset` operation, you will later need
> a new keyword for `Disposal`, because these are two entirely different
> scenarios.
> (Should I explain why?)
>
> In this context, I also see a problem, as if the RFC is trying to
> introduce two different features into the language:
>
> 1. **Scope** – a visibility area. It is the scope that has the `unset` logic.
> 2. **Using** – a guaranteed call of a disposal function.
>
> Because of this, logical issues are likely to arise. If the RFC’s goal
> is unclear and it tries to cover both tasks, the solution risks losing
> its clarity.
>
> P.S.
> Regarding the questions in the Open Issues, option A seems to have
> more explicit behavior than option B.
>
> ---
> Best Regards, Ed


Hello,

Thank you for the feedback.

Regarding the `Disposable` interface: introducing it in the future
won't require new syntax. The `use` construct can work with both
`__destruct` (current behavior) and a future disposal interface.

The idea is to introduce an interface like:

```php
interface Disposable {
  public function dispose(?Throwable $throwable = null): void;
}
```

With `use`:

```php
use ($foo = new Something()) {
  // work
} // ->dispose(null) called on success, ->dispose($exception) on failure
```

This mimics Python's context manager protocol. The `dispose()` method
would be called before `__destruct`, allowing objects to distinguish
between successful completion and failure.

However, there's nothing stopping us from shipping without it. The
lock example in the RFC doesn't need this, locks are freed
automatically in `__destruct`. The initial version relying solely on
`__destruct` works fine for most use cases.

**On the name "Disposable"**: I'm not really a fan of this name
myself. It was just my initial thinking when trying to copy Hack. We
can come up with something better later.

**On Hack's approach**: Hack has a `Disposable` interface, but it
works differently: disposable objects must maintain refcount=1, can't
be assigned to properties, and functions returning disposables need
`<<__ReturnDisposable>>`. This is enforced statically by their
analyzer. At runtime, they're just regular PHP objects. We can't
replicate this in PHP.

**The refcount problem**: A disposal interface has its issues. Once
`dispose()` is called, there may still be references to the object
somewhere, leaving it in an undesirable state, unless we add a way to
enforce refcount = 1.

A disposal interface without exception awareness brings limited value.
But with `?Throwable`, it becomes useful:

```php
use ($transaction = $ctx->beginTransaction()) {
  // work
} // Transaction::dispose(?Throwable) called, then __destruct
```

Without `dispose(?Throwable)`, the transaction can't know whether to
commit or rollback, `__destruct` alone can't distinguish success from
failure.

**The key point**: the initial version (relying on `__destruct`) and a
future disposal interface don't conflict.

Thanks,
Seifeddine Gmati.

Reply via email to