Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 28, 2012 [Issue 9087] New: Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
http://d.puremagic.com/issues/show_bug.cgi?id=9087 Summary: Value modified in foreach warning Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: enhancement Priority: P2 Component: DMD AssignedTo: nobody@puremagic.com ReportedBy: bearophile_hugs@eml.cc --- Comment #0 from bearophile_hugs@eml.cc 2012-11-27 18:41:03 PST --- Currently (DMD 2.061alpha) this code generates a warning: // program#1 void main() { foreach (i; 0 .. 10) i++; } test.d(4): Warning: variable modified in foreach body requires ref storage class This is a rather common and well known source of bugs in D code (C# disallows such mutation): // program#2 struct S { int x; } void main() { auto items = [S(1), S(2), S(3)]; foreach (it; items) it.x++; } (The bug is that the programmer thinks she has modified the contents of "items" array, while the changes are just in the "it" copy, and such changes get lost silently.) So to both help avoid those common bugs, and improve consistency between the two cases, I suggest to generate a warning in program#2 too, similar to: test.d(6): Warning: mutable value modified in foreach body requires ref storage class -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-27 19:31:53 PST --- (In reply to comment #0) > Currently (DMD 2.061alpha) this code generates a warning: > > // program#1 > void main() { > foreach (i; 0 .. 10) > i++; > } > > test.d(4): Warning: variable modified in foreach body requires ref storage > class This is the *temporary* warning in progress of fixing bug 6652. Finally, the warning will be disappeared and modifying non-ref foreach key will be acceptable. This means that the warning is not for the purpose you hope. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #2 from bearophile_hugs@eml.cc 2012-11-27 19:49:45 PST --- (In reply to comment #1) > This means that the warning is not for the purpose you hope. I see, thank you for the answer Hara. But I think the warning I am asking here is one of the better solutions to avoid those bugs. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #3 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-27 20:23:02 PST --- (In reply to comment #2) > But I think the warning I am asking here is one of the better solutions to avoid those bugs. Yes, in many case those *bugs* will be avoided by your enhancement. However, in few cases, if a user really wants to use the foreach key as a mutable copy of iterated element, your enhancement will reject such *correct* code. At least, that is a point described in the bug 6652 comment#0. Therefore, this is a design selection. One is avoiding "non-effect modification" bugs with blocking a few valid code. Another is to keep language expressive with a little more user's learning. I stand on latter, in basic. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #4 from bearophile_hugs@eml.cc 2012-11-28 05:13:30 PST --- (In reply to comment #1) > This is the *temporary* warning in progress of fixing bug 6652. Finally, the warning will be disappeared and modifying non-ref foreach key will be acceptable. Are you saying this will be accepted with no warnings nor errors? void main() { foreach (i; 0 .. 10) i++; } This means extending a bug-prone behavour of D. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #5 from bearophile_hugs@eml.cc 2012-11-28 05:14:12 PST --- (In reply to comment #3) > Another is to keep language expressive with a little more user's learning. 1) Learning to avoid bugs is a very painful process, it takes lot of time, and some bugs escape even the most precise programmers. Experience shows that automatic tools (like the compiler) are needed. 2) Modifying a copy of a struct/value in a foreach is a rare operation. And there is no significant decrease in D expressiveness, because there are other ways to do it: // program#3 struct S { int x; } void main() { auto items = [S(1), S(2), S(3)]; foreach (it; items) { auto itc = it; itc.x++; } for (size_t i = 0; i < items.length; i++) { auto it = items[i]; it.x++; } } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 Jonathan M Davis <jmdavisProg@gmx.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jmdavisProg@gmx.com --- Comment #6 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-11-28 08:20:30 PST --- And why should we take a performance hit with a required copy just because you're worried about the stray mistake where someone mutated a foreach variable? Honestly, I don't think that I have _ever_ seen a bug caused by this. That doesn't mean that it can't happen or that it hasn't happened, but I don't think that it's even vaguely worth worrying about. You have a habit of trying to get warnings created for every single stray mistake that you think a programmer might make, and I think that that approach will ultimately lead to a language that is extremely annoying to use. There comes a point where you have to let the programmer do their job and assume that they're not going to be an idiot. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #7 from bearophile_hugs@eml.cc 2012-11-28 14:17:31 PST --- (In reply to comment #6) Thank you for your answers, Jonathan. > And why should we take a performance hit with a required copy I think you are missing something. If you use "ref" or "const ref" no copy is performed: // program#4 struct S { int x; } void main() { auto items = [S(1), S(2), S(3)]; foreach (ref it; items) it.x++; } In program#3 there was a copy because in that case the programmer do wants a copy. > Honestly, I don't think that I have _ever_ seen a bug caused by this. Assuming you have understood what's the bug-class I am talking about (and I am not sure of this, given what I think is the above mistake of yours), yours is only one data point. Mine is another data point, and in my code the unwanted modification of a struct in a foreach loop has caused me several bugs. And in the D newsgroup some other persons have said they make mistakes about this. Another important data point is the design of C#, that in the case discussed in this enhancement request disallows mutation. So in the end it's quite more one person against your case. > That doesn't mean that it can't happen or that it hasn't happened, but I don't think that it's even vaguely worth worrying about. It seems to be a common enough situation that's recognized as bug prone. So it's worth worrying about, because this class of problems is not hard to prevent. > You have a habit of trying to get warnings created for every single stray mistake that you think a programmer might make, I agree that raising a warning here is a suboptimal solution. I think the right solution is to do something more similar to C#, and disallow the struct mutation in foreach unless you put a "ref" tag. The total number of warnings I am asking for in Bugzilla is really small, probably around 3-4. > There comes a point where you have > to let the programmer do their job and assume that they're not going to be an > idiot. We are *very* far from that in D, for a D programmer there are plenty of things to take care of to write correct programs :-) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
November 28, 2012 [Issue 9087] Value modified in foreach warning | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile_hugs@eml.cc | http://d.puremagic.com/issues/show_bug.cgi?id=9087 --- Comment #9 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-11-28 15:08:58 PST --- > I think you are missing something. If you use "ref" or "const ref" no copy is performed: If don't want a copy, then use ref. If you want a copy, then don't use ref. Disallowing mutating the loop variable if not using ref would be annoying. It would force you to manually copy the loop variable if you wanted to mutate it. If we were doing that, we might as well make the loop variable always ref. I think that that's a horrible idea. And warning about something is as good as disallowing, because it's an error for anyone compiling with -w and it's terrible practice to leave any warnings in your code anyway. I understand that there may be bugs caused by failing to use ref when you meant to, but you're basically proposing that a foreach loop always use ref and that anyone wanting it to not be ref must copy the loop variable themselves. Not to mention, in some cases, you _can't_ use ref (e.g. if iterating over a range, and its front doesn't return by ref), which would mean that you'd have to make a useless copy of a non-ref variable in that case. So, I think that a warning like you propose is completely untenable. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
Copyright © 1999-2021 by the D Language Foundation