Peter Alexander:
> Am I the only person that gets caught by this trap?
I have being hit by this bug some times. I think this is a common enough bug in D code. But it's not easy to invent a way to solve it.
----------------
Jonathan M Davis:
> I really don't know how we could make it easier for you to avoid this error
> without making it impossible to other, useful things. But your code works if
> you use ref. You just have to remember to do that.
To "just remember" to avoid the bug is an option, but programmers are not perfect.
One possible solution is to generate a warning when a mutable struct copy is done. But I think this causes too many false positives (false alarms). In theory the compiler may avoid showing the warning if the copied mutable struct is _clearly_ not modified inside the loop body. This reduces the number of false positives, but I think not enough.
Another possible solution is to require something in the foreach, like "ref" or "copy" (or "dup" instead of "copy"). Here I think it's clear that 'v' is a copy of the struct of 'vs' (maybe "copy" is not required if 'v' is not mutable):
struct Vector {
void normalize() { this /= length; }
}
Vector[] vs;
foreach (copy v; vs)
v.normalize();
A mix of the two ideas is to generate the warning unless a "copy" or "ref" is present when there is a mutable copy. So "copy" is used just to silence the warning.
Or maybe just an inlined comment /*copy*/ is needed to silence the warning/error:
foreach (/*copy*/ v; vs)
v.normalize();
Or a different foreach:
foreach_copy (v; vs)
v.normalize();
I think none of the ideas I've shown is good enough.
Bye,
bearophile