Bug 11307 – Make const(T).init and immutable(T).init lvalues
Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-20T10:27:00Z
Last change time
2014-04-28T06:58:42Z
Assigned to
nobody
Creator
monarchdodra
Comments
Comment #0 by monarchdodra — 2013-10-20T10:27:04Z
".init" is a global property, that is marked as rvalue, to prevent it being modified. This is correct behavior.
However, when "T" is const/immutable already, then it is illegal to modify it anyways. Making ".init" an lvalue for such cases has advantages.
First, when writing "foo(const(T).init)", or "tmp = const(T).init", then pass by const reference will be preferred over pass by value.
Second, a "common" use case, to memcpy initialize. This usually looks something like:
T tmp = void;
immutable(T) init = immutable(T).init;
memcpy(&tmp, &init, T.sizeof);
Making a local copy (on the stack, or in static space) is gratuitous, and can be avoided entirelly. This should work:
T tmp = void;
memcpy(&tmp, &immutable(T).init, T.sizeof);
This code actually happens relatively often, in array and appender.
So that's the ER. Nothing huge. Just keeping the T.init lvalue if T is const (or immutable). There's no reason to make it rvalue.
Comment #1 by andrej.mitrovich — 2014-04-26T19:02:13Z
Does lvalueOf help with this?
Comment #2 by monarchdodra — 2014-04-26T20:56:05Z
(In reply to Andrej Mitrovic from comment #1)
> Does lvalueOf help with this?
Not really. All `lvalueOf` does is provide an "external" lvalue you can test for your traits/contraints, but it doesn't actually provide an actual instance you can read or use.
Comment #3 by k.hara.pg — 2014-04-28T05:15:08Z
(In reply to monarchdodra from comment #0)
> ".init" is a global property, that is marked as rvalue, to prevent it being
> modified. This is correct behavior.
>
> However, when "T" is const/immutable already, then it is illegal to modify
> it anyways. Making ".init" an lvalue for such cases has advantages.
Not only to prevent its modification, T.init makes an rvalue to prevent copy construction on its usage.
auto t = T.init;
If T.init returns an lvalue, initializing t will always invoke T's postblit if exists.
Comment #4 by monarchdodra — 2014-04-28T06:58:42Z
(In reply to Kenji Hara from comment #3)
> (In reply to monarchdodra from comment #0)
> > ".init" is a global property, that is marked as rvalue, to prevent it being
> > modified. This is correct behavior.
> >
> > However, when "T" is const/immutable already, then it is illegal to modify
> > it anyways. Making ".init" an lvalue for such cases has advantages.
>
> Not only to prevent its modification, T.init makes an rvalue to prevent copy
> construction on its usage.
>
> auto t = T.init;
>
> If T.init returns an lvalue, initializing t will always invoke T's postblit
> if exists.
I think that's good enough of a reason to not implement this.