First Draft: Static Single Assignment
Peter C
peterc at gmail.com
Sat Nov 29 07:56:03 UTC 2025
On Saturday, 29 November 2025 at 01:14:26 UTC, Peter C wrote:
>
> 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.
>
> ....
oops. I got it wrong:
class Data { int value = 1; }
void main()
{
final Data c = new Data(); // Establish a fixed storage
location for the variable.
c.value = 42; // ok fine. object itself is mutable,
c = new Data(); // Error (SAA): Cannot reassign a 'final'
variable.
performCheck(c);
// Caller guarantee: 'c' will still refer to the same object it
was initialized with
writeln("\nValue: ", c.value);
}
// According to the DIP:
// "A ref cannot be taken of a final declaration:"
// So the compiler would indeed catch this:
void performCheck2(ref Data obj) "Error: Cannot pass a final
variable as a ref parameter."
{
//..
}
// An alternative (the standard, pass by value):
// But, if the parameter obj is reassigned before mutation, the
mutation will apply to a new, unintended object, thus breaking
the caller's intent to have their original object modified.
void performCheckAlt(Data obj)
{
obj = new Data();
obj.value = 42; // This results in a failure of the callers
intent.
}
// Did it violate final c? No. The variable c was never
reassigned.
// Did it violate caller's intent? Yes. The caller expected the
original object's value to change, but the function accidentally
created and modified a different object.
// The Solution: Constrain the Parameter:
void performCheck_Safe(final Data obj)
{
obj = new Data(); // Error (SAA): Cannot reassign a 'final'
variable.
obj.value = 42; // Guarantee: mutation applies to the
caller's object
}
More information about the dip.development
mailing list