RFC: scope and borrowing

bearophile via Digitalmars-d digitalmars-d at puremagic.com
Wed Aug 27 04:47:20 PDT 2014


Marco Leise:

> The amount of possible use-cases you listed for this extension
> is staggering.

With scope management in code like this:


import std.stdio, std.algorithm;
int foo(in int[] a) {
     return sum([0, 1] ~ a[1 .. $ - 2] ~ 0 ~
                [a[$ - 1] + 1, a[$ - 1] + 2]);
}
void main() {
     int[5] b = [10, 20, 30, 40, 50];
     b.foo.writeln;
}


The compiler in theory could lower the code to something like 
this, removing all heap allocations for the array literals and 
the concatenations, allowing 'foo' to be annotated with @nogc (I 
don't know if Rust is able to do this, I presume it can):


import std.stdio, std.algorithm, core.stdc.stdlib;
T foo(T)(in T[] a) @nogc {
     immutable size_t L = 2 + a.length - 3 + 1 + 2;
     auto ptr = alloca(T.sizeof * L);
     if (ptr == null)
         exit(1); // Or throw a stack overflow error.
     T[] b = (cast(T*)ptr)[0 .. L];
     b[0] = 0;
     b[1] = 1;
     b[2 .. $ - 3] = a[1 .. $ - 2];
     b[$ - 3] = 0;
     b[$ - 2] = a[$ - 1] + 1;
     b[$ - 1] = a[$ - 1] + 2;
     return sum(b);

}
void main() {
     int[5] c = [10, 20, 30, 40, 50];
     c.foo.writeln;
}


But in some cases you don't want those arrays to be allocated on 
the stack because you know they are very large. So the [...]s 
array literal syntax becomes useful again:

import std.stdio, std.algorithm;
int foo(const scope int[] a) {
     return sum([0, 1]s ~ a[1 .. $ - 2] ~ 0 ~
                [a[$ - 1] + 1, a[$ - 1] + 2]s);
}


But this is still not enough, because even if those parts are all 
safely stack-allocated, the result of the concatenation is still 
not stack-allocated.


This could be enough:

import std.stdio, std.algorithm;
int foo(const scope int[] a) @nogc {
     auto[$] a2 = [0, 1]s ~ a[1 .. $ - 2] ~ 0 ~
                  [a[$ - 1] + 1, a[$ - 1] + 2]s;
     return sum(a2[]);
}

Bye,
bearophile


More information about the Digitalmars-d mailing list