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