First Draft: Static Single Assignment
Peter C
peterc at gmail.com
Sat Nov 29 01:14:26 UTC 2025
On Friday, 28 November 2025 at 00:40:06 UTC, Meta wrote:
>
> The compiler can already guarantee that, because the reference
> to c is passed by value. To pass it by reference and introduce
> such a side effect, the function would have to accept a ref
> Data.
As I understand it, the scope of guarantee for 'final' (or fixed
as I prefer to call it) is only inside the callee's scope.
So, if you pass a 'final' variable into a function, the callee
(the function) only sees the value/reference.
The fact that the caller's variable is 'final' doesn’t constrain
the callee in any way whatsoever.
So there are only two options to ensure the constraint of the
callee remains:
void performCheck(final Data obj) // The parameter becomes a
local variable holding a copy of the reference.
{
obj = new Data(); // Error (SAA): Cannot reassign a 'final'
variable.
obj.value = 1;
}
// Guarantee: Inside the function, all mutations apply to the
same object the caller passed in.
void performCheck(final ref Data obj) // The parameter is an
alias for the caller’s variable itself.
{
obj = new Data(); // Error (SAA): Cannot reassign a 'final'
variable.
obj.value = 1;
}
// Guarantee: The caller's binding is formally protected, not
just incidentally safe.
Practically: Both forms ensure that mutations inside the function
apply to the same object as c, thus ensuring the constraint of
the callee.
So.. back in main():
// We do indeed have a guarantee that here, 'c' will still refer
to the same object it was initialized with: writeln("\nValue: ",
c.value);
Actually, now that I think about it, this example makes the case
for transitivity of 'final's binding guarantee (i.e. like C#'s
readonly).
Otherwise, it's a pretty loose guarantee, and it becomes more
about style and clarity than about strong enforcement across the
call graph.
A developer reading the code can’t be sure whether the “single
assignment” promise holds everywhere or just in one scope!
In my opinion, for it to be valuable, the compiler would need to
enforce a "no rebinding anywhere" rule, which I think is outside
the scope of this DIP?
With transitivity, it becomes a strong, system-wide contract,
much like C#'s readonly.
More information about the dip.development
mailing list