[Dlang-internal] DIP1000 discussion and testing

Walter Bright via Dlang-internal dlang-internal at puremagic.com
Mon Oct 31 02:53:30 PDT 2016


On 10/31/2016 1:08 AM, Dicebot wrote:
> On Monday, 31 October 2016 at 06:43:48 UTC, Walter Bright wrote:
>> If the returned pointer is or is not derived from the value of the  scope
>> parameter is immaterial, the caller will act as if it is - meaning that the
>> scope of the returned value will be restricted to being the same scope of the
>> argument.
>
> Is it how you want to change the implementation or how you intend it to work
> now? Because currently it acts differently and no lifetime restriction ever
> happens in absence of explicit `return scope` annotation:
>
> int* foo ( scope int* );
> int* global;
>
> void main () {
>     scope int* ptr;
>     global = foo(ptr); // compiles
> }

Amending it as follows:

   @safe int* foo ( return scope int* );
   int* global;

   @safe void main () {
     scope int* ptr;
     global = foo(ptr); // compiles
   }

Produces:

   ..\dmd bug -transition=safe
   DMD v2.069 DEBUG
   bug.d(6): Error: scope variable ptr assigned to global with longer lifetime

which works as intended and is the current behavior.

'scope' means the value does not escape the function.

'return scope' means the value does not escape the function, but may be returned.

It's analogous to 'ref' and 'return ref' parameters. It works the same way, 
except it pertains to the value of the argument rather than its address.

I'm a bit baffled why I am unable to explain this.



> -----------------------------
>
> Let's get back to the old snippet as you haven't answered my question:
>
> struct Tree
> {
>     Node* head;
>
>     TreeRange range ( ) scope;
> }
>
> Per my understanding, it is roughly equivalent to this:
>
> struct Tree { Node* head; }
> TreeRange range ( scope ref Tree this );

Yes. Note that you can ALWAYS rewrite member functions as normal functions with 
the 'this' parameter as a regular parameter. There is nothing magically 
different about them, they MUST MUST MUST behave the same way. Otherwise, 
nothing will make sense.


> With current rules `scope` here is completely ignored because `this` is already
> a reference and thus is not allowed to escape. And `TreeRange` lifetime has no
> relation with `this` lifetime, because such relation is only defined by `return
> scope`/`return ref`.

Again, 'ref' refers to the ADDRESS of the argument. 'scope' refers to the VALUE 
of the argument.

1. 'return ref' says that the function returns that parameter by 'ref' (or is 
treated as if it did).

2. 'return scope' says that the function returns that parameter by value (or is 
treated as if it did).

3. 'return ref scope' is treated as 'return ref' and 'scope' if the function 
returns by ref.

4. 'return ref scope' is treated as 'ref' and 'return scope' if the function 
does not return by ref.

Therefore,

     TreeRange range(scope ref Tree this);

is case 4, and the return value of 'range' will have the scope of the value of 
the argument corresponding to 'this', which corresponds to the scope of the 
argument.

> Now in http://forum.dlang.org/post/nusi80$4h0$1@digitalmars.com you propose to
> make so that such `scope` annotation does indeed transfer lifetime: ".. the
> design ignores 'scope' if it is applied to a variable with no indirections. But
> we can make it apply". But that does not seem applicable to discussed example as
> struct Tree does contain indirections.

My proposed change is to make it apply even if it does not contain indirections.

> Another issue is that would be completely out of line from existing difference
> between `scope` and `return scope`.

I don't think that is at all the case.



More information about the Dlang-internal mailing list