I had this working earlier, but subsequent fixes broke it:
struct T {
const(int)* p = null;
this(const(int)* q) pure {
p = q;
}
}
void foo() {
int x;
T p1 = T(&x); // ok
// immutable(T) p2 = T(&x); // error
immutable int y;
immutable(T) p3 = T(&y); // line 14, should be ok
immutable(T)* p4 = new T(&y); // line 15, should be ok
}
C:\cbx\mars>dmd -c foo
DMD v2.066 DEBUG
foo.d(14): Error: cannot implicitly convert expression ((T __ctmp2 = T;
, __ctmp2).this(& y)) of type T to immutable(T)
foo.d(15): Error: cannot implicitly convert expression (new T(& y)) of type T* to immutable(T)*
The non-constructor version of it also fails:
struct S {
const(int)* p;
}
void bar() {
int x;
// immutable(S)* q1 = new S(&x); // Error, &x is not unique
immutable(S)* q2 = new S(null); // Ok
immutable y = 3;
immutable(S)* q3 = new S(&y); // line 11, this should work
immutable(S)* q4 = new S(new int); // Ok
immutable(int)* i2;
immutable(S)* q5 = new S(i2); // line 14, this should work
pure int* foo();
immutable(S)* q6 = new S(foo()); // Ok
}
C:\cbx\mars>dmd -c foo2
DMD v2.066 DEBUG
foo2.d(11): Error: cannot implicitly convert expression (new S(& y)) of type S* to immutable(S)*
foo2.d(14): Error: cannot implicitly convert expression (new S(cast(const(int)*)i2)) of type S* to immutable(S)*
It's critical that these get fixed.
Comment #1 by bugzilla — 2014-09-17T07:09:04Z
I take it back, this is an enhancement not a regression. Changing the const(int) to immutable(int) will cause the examples to work.
But I'd still like the examples to work as is.
Comment #2 by k.hara.pg — 2014-09-17T11:07:04Z
There's
> struct T {
> const(int)* p = null;
> this(const(int)* q) pure {
> p = q;
> }
> }
When we see only the signature (const(int*)) pure, the constructor cannot construct immutable object in general, because the parameter q may receive mutable object.
If you want to restrict constructed object qualifier by using constructor argument qualifiers, you can use inout constructor.
struct T
{
const(int)* p = null;
this(inout(int)* q) inout// pure
{
p = q;
}
}
void foo()
{
int x;
T mt1 = T(&x); // ok
T* mp1 = new T(&x); // ok
//T mt2 = immutable T(&x); // NG
//T* mp2 = new immutable T(&x); // NG
immutable int y;
//immutable(T) it1 = T(&y); // NG
//immutable(T)* ip1 = new T(&y); // NG
immutable(T) it2 = immutable T(&y); // ok
immutable(T)* ip2 = new immutable T(&y); // ok
}
Comment #3 by k.hara.pg — 2014-09-17T11:13:34Z
(In reply to Kenji Hara from comment #2)
> There's
Sorry, ignore this part.
Comment #4 by dfj1esp02 — 2014-09-17T13:44:02Z
Doesn't work:
---
struct B
{
const(int)[] a;
}
immutable(B) b(immutable int[] a) pure
{
return B(a);
}
---
Error: cannot implicitly convert expression (B(cast(const(int)[])a)) of type B to immutable(B)
Comment #5 by k.hara.pg — 2014-09-17T14:10:50Z
(In reply to Sobirari Muhomori from comment #4)
> Doesn't work:
> ---
> struct B
> {
> const(int)[] a;
> }
>
> immutable(B) b(immutable int[] a) pure
> {
> return B(a);
> }
> ---
> Error: cannot implicitly convert expression (B(cast(const(int)[])a)) of type
> B to immutable(B)
It's equivalent with:
struct B
{
const(int)[] a;
}
void main()
{
immutable int[] a;
immutable(B) b = B(a);
// <-- B is not implicitly convertible to immutable(B)
}
Comment #6 by dfj1esp02 — 2014-09-18T09:21:04Z
It feels like everything constructed in a strongly pure call can be implicitly casted to immutable. A call to pure constructor can be seen as a call to pure factory, so its result can be casted to immutable if the call is strongly pure.
This works:
---
int[] a() pure
{
return new int[2];
}
void b()
{
immutable int[] c = a();
}
---
Comment #7 by robert.schadek — 2024-12-13T18:27:02Z