Thread overview
[Issue 10921] New: scoped returns a reference to an uninitialized object
Aug 29, 2013
Andrej Mitrovic
Aug 29, 2013
Andrej Mitrovic
Aug 29, 2013
Andrej Mitrovic
Aug 30, 2013
Kenji Hara
Aug 30, 2013
Andrej Mitrovic
August 29, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10921

           Summary: scoped returns a reference to an uninitialized object
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrej.mitrovich@gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-08-29 06:58:59 PDT ---
-----
import std.conv;
import std.typecons;

class Point
{
    this(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    int x;
    int y;
}

void main()
{
    auto p1 = scoped!Point(1, 2);
    assert(p1.x == 1, p1.x.text);  // ok
    assert(p1.y == 2, p1.y.text);  // ok

    Point p2 = scoped!Point(1, 2);
    assert(p2.x == 1, p2.x.text);  // fails, == 0
    assert(p2.y == 2, p2.y.text);  // fails, == 0
}
-----

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 29, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10921



--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-08-29 07:01:00 PDT ---
Note however that it only fails when declaring, not when assigning. The following works properly:

-----
import std.conv;
import std.typecons;

class Point
{
    this(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    int x;
    int y;
}

void main()
{
    auto p1 = scoped!Point(1, 2);
    assert(p1.x == 1, p1.x.text);  // ok
    assert(p1.y == 2, p1.y.text);  // ok

    Point p2 = p1;
    assert(p2.x == 1, p2.x.text);  // ok
    assert(p2.y == 2, p2.y.text);  // ok
}
-----

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 29, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10921



--- Comment #2 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-08-29 07:04:28 PDT ---
(In reply to comment #0)
> -----
>     Point p2 = scoped!Point(1, 2);
>     assert(p2.x == 1, p2.x.text);  // fails, == 0
>     assert(p2.y == 2, p2.y.text);  // fails, == 0
> }
> -----

I see now what's going on, the internal voldemort type `static struct Scoped` has a dtor, and it is called because this struct is thrown away when you just want to assign the reference to the object at the call site.

So the bug report itself is invalid, however this should really be documented because it's very hard to spot what went wrong.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10921



--- Comment #3 from Kenji Hara <k.hara.pg@gmail.com> 2013-08-29 18:38:53 PDT ---
(In reply to comment #2)
> (In reply to comment #0)
> > -----
> >     Point p2 = scoped!Point(1, 2);
> >     assert(p2.x == 1, p2.x.text);  // fails, == 0
> >     assert(p2.y == 2, p2.y.text);  // fails, == 0
> > }
> > -----
> 
> I see now what's going on, the internal voldemort type `static struct Scoped` has a dtor, and it is called because this struct is thrown away when you just want to assign the reference to the object at the call site.
> 
> So the bug report itself is invalid, however this should really be documented because it's very hard to spot what went wrong.

We should disable the implicit conversion from Scoped to Point.
I think we can use Proxy mixin instead of alias this for the purpose.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10921



--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-08-30 06:42:16 PDT ---
(In reply to comment #3)
> We should disable the implicit conversion from Scoped to Point.

Maybe.. but I have a feeling this would break code. E.g.:

void callback(scoped Event event) { }
auto event = scoped!Event(...);
callback(event);  // implicit, but OK

Now if the 'scope' storage class actually did something useful in a parameter list, then the above would also be safe.

I suppose you want this to become:
callback(cast(Event)event);

I could live with that, but I'm not sure if any code for other people would break. I hear relatively little about people using scoped (most people seem to use emplace instead).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------