Bug 10138 – Regression (2.063 git-head): Using ReturnType with scoped no longer works
Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-05-22T19:38:00Z
Last change time
2013-05-27T15:39:22Z
Assigned to
nobody
Creator
andrej.mitrovich
Comments
Comment #0 by andrej.mitrovich — 2013-05-22T19:38:35Z
-----
import std.traits;
import std.typecons;
class A
{
}
class B
{
ReturnType!(scoped!A) a; // L12
this()
{
a = scoped!A();
}
}
void main()
{
}
-----
2.062: ok
2.063 git-head:
test.d(12): Error: template instance ReturnType!(scoped) does not match template declaration ReturnType(func...) if (func.length == 1 && isCallable!(func))
This is a breaking change. The workaround is to use 'typeof(scoped!A())'. This workaround was not documented either.
Note that we should consider moving the inner Voldemort type to be a module-scoped templated struct (e.g. 'Scoped'), so the API is easier to use if you use scoped!() for member variables, e.g.:
-----
class B
{
Scoped!A a; // better API
this()
{
a = scoped!A();
}
}
-----
This is all based on the assumption that using scoped for member variables is something that is supported. There are currently no unittests that try to declare scoped variables, hence why this should either become an official feature or it should be properly documented as disallowed.
The code had a hidden bug with 2.062 dmd and earlier.
If class A has two ctors - one is default, another has arguments, and initialize scoped value in B's ctor by calling argument version ctor, it had caused errors.
import std.traits;
import std.typecons;
class A
{
this() {}
this(int) {}
}
class B
{
ReturnType!(scoped!A) a; // L12
this()
{
a = scoped!A(1); // L16
}
}
void main()
{
}
Errors with 2.062:
test.d(16): Error: function std.typecons.scoped!(A).scoped.Scoped!(A).Scoped.opAssign (Scoped!(A) p) is not callable using argument types (Scoped!(A))
test.d(16): Error: cannot implicitly convert expression (scoped(1)) of type Scoped!(A) to Scoped!(A)
In fact, the type you had extract by using ReturnType!(scoped!A) had not been correct scoped value type. The bug has fixed by phobos/pull/1215, therefore the OP code is invalid right now.
In conclusion, this is not a regression.
Comment #3 by andrej.mitrovich — 2013-05-27T06:16:05Z
(In reply to comment #2)
> therefore the OP code is invalid right now.
> In conclusion, this is not a regression.
Ok, but we should at least add a comment somewhere. I think I'll add it to the changelog perhaps..
Comment #4 by andrej.mitrovich — 2013-05-27T14:51:41Z
(In reply to comment #2)
> In fact, the type you had extract by using ReturnType!(scoped!A) had not been
> correct scoped value type. The bug has fixed by phobos/pull/1215, therefore the
> OP code is invalid right now.
>
> In conclusion, this is not a regression.
Here's the thing, though. In that phobos pull, monarchdodra commented with:
"Finally, I gave Scoped an @disabled this() to prevent our smarter users from trying to build a Scoped using typeof."
It seems like he is actively trying to *disallow* using either ReturnType or typeof in order to create a scoped field variable.
But, typeof still works. In 2.063 your example code will become:
-----
class A
{
this() {}
this(int) {}
}
class B
{
typeof(scoped!A()) a;
this()
{
a = scoped!A(); // ok
a = scoped!A(1); // ok
}
}
-----
So now I can't tell whether we *support* using scoped field variables or is the above just a hack? I need to know what to put in the changelog.
Comment #5 by k.hara.pg — 2013-05-27T15:39:22Z
(In reply to comment #4)
> Here's the thing, though. In that phobos pull, monarchdodra commented with:
>
> "Finally, I gave Scoped an @disabled this() to prevent our smarter users from
> trying to build a Scoped using typeof."
>
> It seems like he is actively trying to *disallow* using either ReturnType or
> typeof in order to create a scoped field variable.
>
> But, typeof still works. In 2.063 your example code will become:
[snip]
You are confusing about @disable for `Scoped` struct default construction and calling `scoped` function with zero argument.
If new A() is valid, scoped!A() is also valid. The latter is corresponding to the former. It's the design of scoped utility.
> So now I can't tell whether we *support* using scoped field variables or is the
> above just a hack? I need to know what to put in the changelog.
The rejected case from 2.063 is this:
class A
{
this() {}
this(int) {}
}
class B
{
typeof(scoped!A()) a;
this() // L12
{
//a = scoped!A();
//a = scoped!A(1);
}
}
Output:
test.d(12): Error: constructor test.B.this field a must be initialized in constructor
The field B.a is must be initialized in constructor, comes from the @disable this() defined in typeof(scoped!A()) struct.
However, getting the type of Scoped struct by using typeof is still allowed. So
typeof(scoped!A()) a;
is valid from 2.063.