D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4966 - Loops and closures break immutable
Summary: Loops and closures break immutable
Status: RESOLVED DUPLICATE of issue 2043
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 critical
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2010-10-01 03:42 UTC by nfxjfg
Modified: 2010-11-19 08:59 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description nfxjfg 2010-10-01 03:42:16 UTC
Closures referencing immutable variables declared inside a loop can observe how these immutable values are changing - this should be impossible according to the definition of "immutable".

$ cat closure.d
import std.stdio;

void main() {
    void delegate() res;
    foreach (i; 0..2) {
        immutable v = i;
        void printi() {
            writefln("ptr=%x value=%d", &v , v);
        }
        if (i == 0) {
            res = &printi;
            res();
        }
    }
    res();
}

$ dmd closure.d
$ ./closure
ptr=b75bae44 value=0
ptr=b75bae44 value=1

As you can see, an immutable variable changed its value. The code above is SafeD clean, i.e. doesn't use any dirty tricks that would subvert the typesystem. (Except printing the pointer address, which is just for demonstrating that it's the same value.)
Comment 1 Bruno Medeiros 2010-11-19 08:59:45 UTC
There is not just one variable 'v', there are several "instances" of variable 'v', each of them created on each iteration of the loop. Each of them is immutable during its lifecycle (and cease to exist after their lifecycle, by definition).

The orthogonal solution is:
 * make each 'v' variable be heap-allocated (have unscoped lifecycle). This is consistent to how variables work in the top scope in functions.

I'm starting to reconsider though, if closures should automatically make variables be heap-allocated. Maybe its best to require a keyword/annotation in such referenced variables, and make the code not compile if such keywords is not present.

*** This issue has been marked as a duplicate of issue 2043 ***