Phobos is now compiled with -preview=dip1000

Meta jared771 at gmail.com
Fri May 17 17:03:51 UTC 2019


On Friday, 17 May 2019 at 05:32:42 UTC, Mike Franklin wrote:
> On Friday, 17 May 2019 at 05:22:30 UTC, Mike Franklin wrote:
>
>> My assessment (which could be wrong):
>> `scope` and `return` only apply to pointers and `ref`s.  If 
>> you remove all `scope` and `return` attributes from the 
>> function `push`, it works fine.
>>
>> I consider it a bug that the compiler doesn't emit an error 
>> when using attributes on types for which they are not intended.
>>
>> Mike
>
> Working example:  https://run.dlang.io/is/TCP0td

That does compile, but I don't think that it's working the way I 
want it to. I believe it only works because a GC-managed string 
is used for the backing storage. If you change that to a static 
array on the stack:

@safe
void main()
{
     immutable(char)[16] rawData = "2 6 4 1 0 2 9 4 5";
     auto dataRange = makeDataRange(rawData);
     auto result = dataRange.copyToQueue();
     import std.stdio;
     writeln("The result of data processing is: ", result);
}

It will refuse to compile with this message:
Error: reference to local variable rawData assigned to non-scope 
parameter input calling makeDataRange

`makeDataRange` is defined like this:
@safe
DataRange makeDataRange(string input)
{
     auto range = DataRange(input);
     return range;
}

So that static array is getting implicitly sliced, i.e., its 
address is being taken. It's pretty obvious why `input` is not 
being inferred as scope - it's being returned from 
`makeDataRange`. However, when I try to manually annotate it with 
return or return scope, I run into further errors:

DataRange makeDataRange(return scope string input)
{ ...etc. }

Error: scope variable input assigned to non-scope parameter 
rawData calling DataRange.this
Error: scope variable dataRange assigned to non-scope parameter 
data calling copyToQueue

So I continue annotating things with scope or return or return 
scope whenever the compiler complains about it, going up through 
the call chain until I arrive back at my original problem 
mentioned in the post I linked.

(My original example with changes made going through this 
exercise: https://run.dlang.io/is/uQDXG6)

This is why I say that I'm not sure that I quite understand 
dip1000. I *thought* I did, but an example that seems like it 
should clearly work (at least to me), does not.

If you look at `main` above, `rawData` has the same lifetime as 
the `dataRange` struct returned from `makeDataRange` and the 
queue returned from `copyToQueue`. True, there is some 
traditionally unsafe stuff happening in between; however, I 
thought that the point of adding all these annotations is to tell 
the compiler how the lifetimes of these objects propagate up and 
down the call stack, so that it can check that there will be no 
memory corruption. I'm not doing anything here that will result 
in a pointer to an expired stack frame, or otherwise cause memory 
corruption or use after free, or anything like that (*unless* I 
allow either `dataRange` or `result` to escape from the main 
function - which dip1000 correctly disallows).


More information about the Digitalmars-d-announce mailing list