Using inout in delegate

Kenji Hara k.hara.pg at gmail.com
Tue Apr 2 06:03:44 PDT 2013


On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer 
wrote:
> On Thu, 28 Mar 2013 04:34:36 -0400, Jacob Carlborg 
> <doob at me.com> wrote:
>
>> The following code fails to compile:
>>
>> void foo (inout int[] arr)
>> {
>>     auto dg = {
>>         foreach (i, e ; arr) {}
>>     };
>>     dg();
>> }
>>
>> void main ()
>> {
>>     auto a = [3, 4, 5];
>>     foo(a);
>> }
>>
>> Error message:
>>
>> main.d(9): Error: variable main.foo.__lambda1.__aggr1174 inout 
>> variables can only be declared inside inout functions
>> main.d(9): Error: variable main.foo.__lambda1.e inout 
>> variables can only be declared inside inout functions
>>
>> If I remove the delegate everything compiles. Am I doing 
>> something wrong?
>>
>
> Like Timon said, it's a bug in inout design.

I think this is not a hole of inout design. In this case, the 
lambda inside foo should capture 'inout' context pointer.

void foo (inout int[] arr)
{
     auto dg = {
         foreach (i, e ; arr) {}
     };
     pragma(msg, typeof(dg));  // should print "void delegate() 
inout"
     dg();
}

> I'm assuming the issue is that the compiler is trying to 
> generate a struct to hold the stack data for foo, and struct 
> members cannot be inout.

It is true, but in this case, the context which is implicitly 
captured by closure is not directly accessible from programmers. 
So qualifying it 'inout' is safe.

> It is a difficult problem to solve, because inout has two 
> meanings depending on whether it is a parameter/return or a 
> local variable.  At some point, we need to address this, 
> because inout has so much potential, but suffers from some 
> large deficiencies.

And, inout closure cannot escape from enclosing inout function.

auto foo(inout int[] arr)
{
     auto dg = (inout int[] a)
     {
         return arr;   // returns captured inout 'arr'
     };
     return dg;  // escape! (should be rejected statically)
}

If compiler does not reject escape...

void main()
{
     const int[] a = [3, 4, 5];
     auto dg = foo(a);
     // typeof(dg) == inout(int[]) delegate(inout(int[]))
     int[] b = dg([]);
     assert(b.ptr == a.ptr);  // type-system breaking!
}

Kenji Hara


More information about the Digitalmars-d-learn mailing list