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