Fix qualified constructor call semantics.#1726
Conversation
|
Could you please add regression tests for the doHeaderInstantiation changes (or point me to them if I missed them)? If I have and I try to create it like this it fails, right? But this would work. Is this right, and could we remove this limitation? |
They have no bugzilla number, but the last commit implicitly contains the tests for the bug (that is
That is not valid D code, because no-arg constructor is not allowed. |
|
With
Essentially both should be rejected (but this change does not reject the latter now) Because. S s = void;
s.__ctor(1); // __ctor == this(int n) immutable(Note that, D optimizes constructor call in initialization. It is different from C++) |
Ah right, I mistakenly assumed that doHeaderInstantiation had something to do with di generation.
Right, I meant a valid constructor with an argument.
Is this part of the language though, or just dmd's implementation? I see no reason it couldn't be lowered to S s = void;
immutable(S) tmp;
tmp.__ctor(1);
s = tmp;I know that's not valid code, but hopefully you get what I mean. One of the goals of making struct literals rvalues was to make (I'm talking about the |
I can agree that your thought is not invalid, but I can see no benefit in there.
No, a constructor call in variable initializer is treated specially in today's D. In C++, for |
Is this required or is this just an optimization made possible by D's rvalue semantics?
(Is the implicit conversion from/to mutable/immutable even valid if S has a postblit? Have we finished defining this part of the language?) I understand where you're coming from, but you could also say the bad performance is the fault of the high-cost postblit itself, not the language. I think this situation is inconsistent: struct S
{
this(int i) immutable {}
this(this) { beSlow(); }
ref S opAssign(const ref S other) const { beSlow(); }
}
immutable(S) makeS() { return immutable(S)(0); }
void main()
{
immutable(S) s1 = makeS(); // fast, rvalue copy
immutable(S) s2 = immutable(S)(0); // fast, in-place construction
S s3 = makeS(); // slow, postblit called (or is it opAssign?)
S s4 = immutable(S)(0); // not allowed????
} |
Oh, I forgot to mention about that in previous comment. At least it has been enabled from early D2 age (See
I'm planning it in local (unique postblit would be introduced). I should write a new DIP for that.
No, I mean is that postblit (copying) should not run for object construction. If the variable declaration looks like being initialized by constructor call, it should actually not do copying. I think your proposal will destroy the implicit assumption of many D users.
All of them are initializing, not assignment. The last one looks to me that is just a mistaken. |
I recall it being carefully designed to be possible to avoid copies on construction, but I don't know if it is required. If it is then we don't really have a choice here.
Looking forward to it!
I'll have to think more about this. |
|
This is great work. I'm not very sure about the pure constructor; I know there's been some talk about it, are @9rnsr and @WalterBright and others certain this stands scrutiny? |
|
@andralex "unique constructor" is a concept that I call tentatively. Some kind of By using the concept, some That is incredibly useful concept, and I think that we also can improve postblit concept by using it. (introducing "unique postlit" and use it for mutual conversion between mutable and immutable objects. I planning to write new DIP about it.) |
|
@andralex I assume you meant me? I'm happy with the purity related changes in this pull. I think they're in the right direction. |
|
I think we need to add this in 2.063. In 2.063, bug 6578 was partially fixed (by #666), but by that, currently incorrect constructor is easy to be called. struct S {
int[] arr;
this(int[] a) { arr = a; }
}
void main() {
int[] arr = [1,2,3];
auto si = immutable S(arr);
pragma(msg, typeof(si));
pragma(msg, typeof(si.arr));
assert(si.arr == [1,2,3]);
arr[] = 1;
assert(si.arr == [1,1,1]); // !?
}This code compiles and runs successfully with current master. That's really bad. |
|
Temporarily close. |
Confused `this(this)` and `this(this T)`
If the qualified constructor creates isolated object, it is implicitly convertible to any qualified object. And now, inout constructor is properly supported.
|
I'll pull this for now. But I want to work on developing the idea of a "unique constructor". A constructor shouldn't have to be labeled 'pure' in order for it to be unique. It can be inferred to be unique if it consists solely of unique (or immutable) elements. The result of a unique constructor can be implicitly cast to mutable, immutable, or shared. |
Fix qualified constructor call semantics.
|
FYI, a bug I opened was closed due to this pull, but I don't agree with the solution (for inout anyway). http://d.puremagic.com/issues/show_bug.cgi?id=7378 Please comment... |
|
This pull request introduced a regression: |
…thread Add attributes to core.thread
By this change, one of following is required for immutable object construction:
immutable constructor
That is described in TDPL.
inout constructor
The qualifier of generated object by inout constructor is calculated as if that is returned value from inout function.
unique constructor
If a pure constructor can create unique object, the generated object can be implicitly convertible to any qualifier.