Bug 9051 – Passing an immutable global with post-blit to a CTFE function
Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-11-20T12:50:42Z
Last change time
2021-03-16T11:03:31Z
Keywords
diagnostic
Assigned to
No Owner
Creator
Dmitry Olshansky
Comments
Comment #0 by dmitry.olsh — 2012-11-20T12:50:42Z
I'm wondering if this is supposed to work. By all means I don't see why it has to try this(this) in this case (and moreover fail).
struct Set{
uint[] arr;
this(this){ } //comment out to make it compile
}
pure auto getMeASet(uint[] arr)
{
return Set(arr);
}
immutable set = getMeASet([1,2,3,4]);
pure auto getSecond(in Set set)
{
return set.arr[1];
}
pragma(msg, getSecond(set));
And the diagnostic spits all kinds of nonsense:
D:\D\ctfe_glob.d(20): Error: variable ctfe_glob.__cpcttmp6 of type struct const(Set) uses this(this), which is not allowed in static initialization
D:\D\ctfe_glob.d(20): while evaluating pragma(msg, getSecond((const const(Set) __cpcttmp6 = Set([1u, 2u, 3u, 4u]);
, __cpcttmp6)))
Comment #1 by clugdbug — 2012-11-21T02:13:04Z
The error message is not coming from CTFE. Here's a simple case from a comment in the compiler source code (declaration.c):
/* The problem is the following code:
* struct CopyTest {
* double x;
* this(double a) { x = a * 10.0;}
* this(this) { x += 2.0; }
* }
* const CopyTest z = CopyTest(5.3); // ok
* const CopyTest w = z; // not ok, postblit not run
* static assert(w.x == 55.0);
* because the postblit doesn't get run on the initialization of w.
*/
I think that if we didn't call this(this), wrong code would result.
There is at least a diagnostic bug here - if it must behave this way, the code that creates the comma expression should be issuing the error.
Interestingly, if you move it inside a function, the result is different:
void foo()
{
pragma(msg, getSecond(set));
}
qqq.d(19): Error: static variable set cannot be referenced at compile time
qqq.d(19): called from here: __cpcttmp6.__cpctor(set)
qqq.d(19): called from here: getSecond((const const(Set) __cpcttmp6 = __cpcttmp6.__cpctor(set);
, __cpcttmp6))
Comment #2 by dmitry.olsh — 2012-11-21T10:49:17Z
(In reply to comment #1)
> The error message is not coming from CTFE. Here's a simple case from a comment
> in the compiler source code (declaration.c):
>
> /* The problem is the following code:
> * struct CopyTest {
> * double x;
> * this(double a) { x = a * 10.0;}
> * this(this) { x += 2.0; }
> * }
> * const CopyTest z = CopyTest(5.3); // ok
> * const CopyTest w = z; // not ok, postblit not run
> * static assert(w.x == 55.0);
> * because the postblit doesn't get run on the initialization of w.
> */
>
> I think that if we didn't call this(this), wrong code would result.
I agree in general. And But given that getMeASet(uint[] arr) is an r-value. Surely the result of it should be just moved?
The other thought is: can't this(this) be run at compile-time then? What are limitations?
> There is at least a diagnostic bug here - if it must behave this way, the code
> that creates the comma expression should be issuing the error.
>
> Interestingly, if you move it inside a function, the result is different:
>
The same thing happens if you try passing set by reference be it const or otherwise.
> void foo()
> {
> pragma(msg, getSecond(set));
> }
>
> qqq.d(19): Error: static variable set cannot be referenced at compile time
> qqq.d(19): called from here: __cpcttmp6.__cpctor(set)
> qqq.d(19): called from here: getSecond((const const(Set) __cpcttmp6 =
> __cpcttmp6.__cpctor(set);
> , __cpcttmp6))
Comment #3 by clugdbug — 2012-11-26T00:56:22Z
(In reply to comment #2)
> (In reply to comment #1)
> > The error message is not coming from CTFE. Here's a simple case from a comment
> > in the compiler source code (declaration.c):
> >
> > /* The problem is the following code:
> > * struct CopyTest {
> > * double x;
> > * this(double a) { x = a * 10.0;}
> > * this(this) { x += 2.0; }
> > * }
> > * const CopyTest z = CopyTest(5.3); // ok
> > * const CopyTest w = z; // not ok, postblit not run
> > * static assert(w.x == 55.0);
> > * because the postblit doesn't get run on the initialization of w.
> > */
> >
> > I think that if we didn't call this(this), wrong code would result.
>
> I agree in general. And But given that getMeASet(uint[] arr) is an r-value.
> Surely the result of it should be just moved?
>
> The other thought is: can't this(this) be run at compile-time then? What are
> limitations?
Yeah, that's kind of like bug 7988. The calling of this(this) should be part of the CTFE'd bit. CTFE could cope with it, no problem, it just doesn't get a chance. BTW if we moved the this(this) into CTFE, the example I posted would also work!
Comment #4 by razvan.nitu1305 — 2021-03-16T11:03:31Z
The postblit should not be used as it has impossible to fix flaws. Development for it has halted. The code works if the copy constructor is used:
struct Set{
uint[] arr;
this(const ref Set) {} //comment out to make it compile
}
pure auto getMeASet(uint[] arr)
{
return Set(arr);
}
immutable set = getMeASet([1,2,3,4]);
pure auto getSecond(in Set set)
{
return set.arr[1];
}
pragma(msg, getSecond(set));
I'm gonna close this as WONTFIX.