Thread overview
Safe to cast to immutable and return?
Jul 05, 2018
Timoses
Jul 05, 2018
vit
Jul 05, 2018
Timoses
July 05, 2018
Is this safe?

class A {}
immutable(A) getA()
{
    A a;
    // .. do stuff with a
    // not leaking a to any functions

    // is this safe????
    return cast(immutable A)a;
}

What if A is replaced with A[] or A[int]?
If it's not safe, what would be the proper way to return an immutable instance from a function which needs to make adjustments to the instance before returning it as immutable?
July 05, 2018
On Thursday, 5 July 2018 at 11:15:03 UTC, Timoses wrote:
> Is this safe?
>
> class A {}
> immutable(A) getA()
> {
>     A a;
>     // .. do stuff with a
>     // not leaking a to any functions
>
>     // is this safe????
>     return cast(immutable A)a;
> }
>
> What if A is replaced with A[] or A[int]?
> If it's not safe, what would be the proper way to return an immutable instance from a function which needs to make adjustments to the instance before returning it as immutable?

Try pure functions:

class A {}
A getA()pure @safe  //pure whitout mutable parameters guarantees that function doesn't leak data.
{
     A a;
     // .. do stuff with a
     // not leaking a to any functions

     // is this safe????
     return a;
}
A getA2(A x)pure @safe  //pure with mutable param
{
     A a;
     // .. do stuff with a
     // not leaking a to any functions

     // is this safe????
     return a;
}

void test()@safe{
    immutable(A) a1 = getA();        //ok
    immutable(A) a2 = getA2(null);   //ok
    immutable(A) a3 = getA2(new A);  //ok
    immutable(A) a4 = getA2(a3);    //error in theory can leak




}
July 05, 2018
On 7/5/18 7:15 AM, Timoses wrote:
> Is this safe?
> 
> class A {}
> immutable(A) getA()
> {
>      A a;
>      // .. do stuff with a
>      // not leaking a to any functions
> 
>      // is this safe????
>      return cast(immutable A)a;
> }

As in @safe? no. But it's safe in the fact that you aren't escaping any mutable references as immutable. However, casting is dangerous. It disables any checks about const safety that the compiler may do. If something happens to A where it all of a sudden gains a mutable reference, and the reference is to global data or has other references:

class A { int *x; }

int globalx;
immutable(A) getA()
{
   A a = new A;
   a.x = &globalx;
   return cast(immutable A)a;
}

Now it's not safe, and the compiler won't tell you.

> 
> What if A is replaced with A[] or A[int]?

A[] should work very similarly to A

A[int] I think will work, I don't think it stores any type info inside the AA.

The rule is that if you *know* there are no other references to a mutable piece of data, it's OK to cast to immutable.

> If it's not safe, what would be the proper way to return an immutable instance from a function which needs to make adjustments to the instance before returning it as immutable?

See vit's response, he covers it pretty well.

-Steve
July 05, 2018
On Thursday, 5 July 2018 at 12:15:35 UTC, vit wrote:
>
> Try pure functions:
>
> class A {}
> A getA()pure @safe  //pure whitout mutable parameters guarantees that function doesn't leak data.
> {
>      A a;
>      // .. do stuff with a
>      // not leaking a to any functions
>
>      // is this safe????
>      return a;
> }
> A getA2(A x)pure @safe  //pure with mutable param
> {
>      A a;
>      // .. do stuff with a
>      // not leaking a to any functions
>
>      // is this safe????
>      return a;
> }
>
> void test()@safe{
>     immutable(A) a1 = getA();        //ok
>     immutable(A) a2 = getA2(null);   //ok
>     immutable(A) a3 = getA2(new A);  //ok
>     immutable(A) a4 = getA2(a3);    //error in theory can leak
> }

Very nice!
I assume the @safe is not a must?

Good read:
https://dlang.org/spec/function.html#pure-functions