Cannot take slice of scope static array in @safe code

Steven Schveighoffer schveiguy at gmail.com
Sun Feb 2 18:18:28 UTC 2020


On 2/2/20 10:20 AM, ag0aep6g wrote:
> On 02.02.20 14:40, Dennis wrote:
>> Compiling the following with -dip1000 gives an error.
>>
>> ```
>> void main() @safe {
>>      string[1] a0;
>>      scope int[1] a1;
>>      scope string[1] a2;
>>
>>      scope string[] b0 = a0[]; // Fine
>>      scope int[] b1 = a1[]; // Fine
>>      scope string[] b2 = a2[]; // Error: cannot take address of scope 
>> local a2
>> }
>> ```
>>
>> Can anyone explain why? I don't see how b2 violates the scope 
>> constraint of a2.
> 
> To make this easier, let's:
> 
> 1) type out `string` as `immutable(char)[]`,
> 2) throw that `immutable` away, because it doesn't matter,
> 3) replace the arrays with pointers.
> 
> Then we're looking at this:
> 
>      void main() @safe
>      {
>          int* a0;
>          scope int** b0 = &a0; /* accepted */
> 
>          scope int* a2;
>          scope int** b2 = &a2; /* rejected */
>      }
> 
> Now it's important to realize that `scope` only applies to the top-level 
> of the type. That means, when you dereference b0 or b2, you get a plain 
> `int*` without any `scope` on it.

I think this is wrong. a0 is not a scope array of scope strings, it's a 
scope array of strings. string isn't scope, it points to immutable data 
that's on the heap or in the static segment (generally).

This is the biggest problem of dip1000 -- there's just no granularity in 
scope, it applies to EVERYTHING that is referenced from it.

scope should have been a type constructor.

> 
> For b0 that's fine, because a0 isn't `scope` (neither explicit nor 
> inferred).
> 
> But for b2 it would be a problem, because a2 would lose its `scope`. 
> That can't be allowed.
> 
>> It might be a compiler bug, but since the int[] case works
> 
> With regards to DIP 1000, `string` is very different from `int`. 
> `string` has an indirection. `int` doesn't. The analogous type to 
> `string[]` is `int[][]`.

How does one declare "I have this array which is scope, because it's 
storage is on the stack. But it points at things that are in the GC 
heap, so it's cool to reference those without scope."

And if that is a simple matter, what about an array stored on the stack 
of arrays stored on the stack, of references to heap data? How do I make 
sure the heap pointers are still heap pointers, and not have to cast the 
compiler into submission?

I've run into problems like this before, they aren't solvable with 
dip1000. And string arrays are usually where it stops working because of 
the double indirection.

-Steve


More information about the Digitalmars-d-learn mailing list