On Sat, Jan 24, 2026, at 12:16 PM, Tim Düsterhus wrote:
> My understanding the initial paragraph of your email is that the entire
> functionality of the block scoping RFC could be included in the Context
> Manager RFC. The Context Manager RFC uses the same "high-level" syntax
> of having a dedicated block for declarations - just using `using`
> instead of `let` as the keyword and using `=>` instead of `=` for an
> assignment (the latter of which was considered confusing in the
> discussion). I'm sure I must be misunderstanding, because I don't follow
> how the syntax of this RFC is "non-standard and clumsy" without this
> equally applying to the context manager RFC. Can you rephrase?
Block scoping and CMs are related and overlap, but are different things.
`let`, in every language I am aware of that uses it, is an inline part of the
variable declaration, and then they do something to resolve the "dead zone"
question. Languages that have block scoping have had it from the beginning, so
"variable dies at the next }" is built into the language semantics and
development culture. Neither is true in PHP. So having a block-esque syntax
for "only these special blocks and these special variables get block scoping"
is something I have never seen before, and feels very clumsy.
CMs are about packaging up setup/teardown logic to make them reusable, and
therefore more ergonomic. That setup/teardown can and often does include
unsetting variables, but that's not its main purpose. It's just an
implementation detail. In every language with such functionality, it is a
block level construct.
Block scoping as presented here is essentially a "junior, limited CM", with a
future scope of adding a Disposable interface to make it a less-limited CM. I
fundamentally believe that is the wrong way around, and have already discussed
elsewhere (I think) why forcing the context manager (packaged logic) and
context variable (the variable(s) that will need cleanup) to be the same value
is fundamentally limiting and flawed.
I proposed allowing the `using` syntax to handle non-CM objects specifically to
incorporate the "degenerate case" where unsetting is the only meaningful
teardown, and thereby avoid the need for a boilerplate new
JustUnsetTheThing($thing) for the degenerate cases. CMs can also return $this
from enterContext() if appropriate, which would then have the same effect as
the Disposable interface.
So no matter how you slice it, having a separate CM from context variable
provides more flexibility than the proposed `let` syntax, in a consistent and
unified fashion. By tweaking CMs, we can allow it to also cover the simple,
degenerate cases that block scoping handles in addition to the more robust
options it naturally supports.
> I'd also like to note that it was an explicit design goal of the block
> scoping RFC to compose nicely with existing control structures to be
> generically applicable. This enables several of the example use cases
> listed in the RFC. The context manager RFC requires braces and a
> proposed special case for `try` instead of just accepting any statement
> like block scoping does. Due to its composibility, the block scoping RFC
> is even compatible with future additions to the language (provided the
> future additions follow the established syntax). As an example, pattern
> matching comes to mind as another way of "writing into variables". Block
> scoping will just work with match:
>
> let ($x, $y) $result = match ($p) is {
> Point(:$z, :$x, y: 4) => "x is $x, y is 4, z is $z",
> };
>
> to prevent $x and $y from leaking out of the `match()`. And similarly to
> the `foreach()` future scope, we could allow `match ($p) let is` to
> automatically block scope all variables bound by the pattern.
thinking_face.gif
This is sort of what we were trying to noodle through with the questions about
expression-oriented `using`, but it didn't stick. I would have to talk to
Arnaud, but I suppose it's probably possible to allow `using` to work on an
arbitrary construct and inherit its block. I'm quite open to discussing the
feasibility of that.
It's really unfortunate that both proposals were worked on separately, as I do
believe there are good ideas in both. But I would much rather work from the
more-flexible design and then short-cut the degenerate cases, as that gives, I
believe, a better outcome in the end.
--Larry Garfield