February 20, 2011
Hi again,

I just came across something odd - if the aggregate expression in a
foreach statement constructs a new struct (returning an rvalue), it
isn't finalized (well, to be precise, its implicit copy isn't).

Test:
----------
import std.stdio;

struct A
{
    int[3] _data;
    string _name;

    this(string name) { writeln("A.__ctor() for ", name); _name = name; }
    ~this() { writeln("A.__dtor() for ", _name); }
    this(this) { _name ~= "2"; writeln("Postblit constructor for ", _name); }

    A dup()
    {
        A r = A(_name ~ ".dup");
        r._data[] = _data[];
        return r;
    }

    int opApply(int delegate(ref int) dg)
    {
        int r = 0;
        for (int i = 0; i < _data.length; i++)
        {
            r = dg(_data[i]);
            if (r)
                break;
        }
        return r;
    }
}

unittest
{
    A a = A("a");
    a._data = [ 1, 2, 3 ];

    writeln("Iterating through a:");
    foreach (ref e; a)
        writeln(e);

    writeln("\nIterating through a.dup:");
    {
        foreach (ref e; a.dup)
            writeln(e);
        writeln("ending inner scope");
    }
    writeln("inner scope ended");
}
----------

Output:
----------
A.__ctor() for a
Iterating through a:
1
2
3

Iterating through a.dup:
A.__ctor() for a.dup
Postblit constructor for a.dup2
A.__dtor() for a.dup
1
2
3
ending inner scope
inner scope ended
A.__dtor() for a
----------

The problem is remedied by assigning a.dup manually to an lvalue and iterating over that:
----------
...
        A dup = a.dup;
        foreach (ref e; dup)
...
----------

Output:
----------
A.__ctor() for a
Iterating through a:
1
2
3

Iterating through a.dup:
A.__ctor() for a.dup
Postblit constructor for a.dup2
A.__dtor() for a.dup
1
2
3
ending inner scope
A.__dtor() for a.dup2
inner scope ended
A.__dtor() for a
----------

I just figured this out and think it should be considered as bug as it is far from obvious, at least from my point of view.
February 20, 2011
On 20.02.2011 23:34, Martin Kinkelin wrote:
> Hi again,
>
> I just came across something odd - if the aggregate expression in a
> foreach statement constructs a new struct (returning an rvalue), it
> isn't finalized (well, to be precise, its implicit copy isn't).
>
> Test:
> ----------
> import std.stdio;
>
> struct A
> {
>      int[3] _data;
>      string _name;
>
>      this(string name) { writeln("A.__ctor() for ", name); _name = name; }
>      ~this() { writeln("A.__dtor() for ", _name); }
>      this(this) { _name ~= "2"; writeln("Postblit constructor for ", _name); }
>
>      A dup()
>      {
>          A r = A(_name ~ ".dup");
>          r._data[] = _data[];
>          return r;
>      }
>
>      int opApply(int delegate(ref int) dg)
>      {
>          int r = 0;
>          for (int i = 0; i<  _data.length; i++)
>          {
>              r = dg(_data[i]);
>              if (r)
>                  break;
>          }
>          return r;
>      }
> }
>
> unittest
> {
>      A a = A("a");
>      a._data = [ 1, 2, 3 ];
>
>      writeln("Iterating through a:");
>      foreach (ref e; a)
>          writeln(e);
>
>      writeln("\nIterating through a.dup:");
>      {
>          foreach (ref e; a.dup)
>              writeln(e);
>          writeln("ending inner scope");
>      }
>      writeln("inner scope ended");
> }
> ----------
>
> Output:
> ----------
> A.__ctor() for a
> Iterating through a:
> 1
> 2
> 3
>
> Iterating through a.dup:
> A.__ctor() for a.dup
> Postblit constructor for a.dup2
> A.__dtor() for a.dup
> 1
> 2
> 3
> ending inner scope
> inner scope ended
> A.__dtor() for a
> ----------
>
> The problem is remedied by assigning a.dup manually to an lvalue and iterating
> over that:
> ----------
> ...
>          A dup = a.dup;
>          foreach (ref e; dup)
> ...
> ----------
>
> Output:
> ----------
> A.__ctor() for a
> Iterating through a:
> 1
> 2
> 3
>
> Iterating through a.dup:
> A.__ctor() for a.dup
> Postblit constructor for a.dup2
> A.__dtor() for a.dup
> 1
> 2
> 3
> ending inner scope
> A.__dtor() for a.dup2
> inner scope ended
> A.__dtor() for a
> ----------
>
> I just figured this out and think it should be considered as bug as it is far
> from obvious, at least from my point of view.
It looks like the manifestation of
http://d.puremagic.com/issues/show_bug.cgi?id=3516
vote up ! ;)

-- 
Dmitry Olshansky