On Thursday, 23 August 2018 at 08:48:15 UTC, Walter Bright wrote:
On 8/22/2018 3:52 AM, Atila Neves wrote:
On Wednesday, 22 August 2018 at 09:05:13 UTC, Walter Bright wrote:
On 8/21/2018 8:58 PM, Nicholas Wilson wrote:
On Tuesday, 21 August 2018 at 14:31:02 UTC, Atila Neves wrote:
The problem is that the code we write doesn't deal directly with pointers - see the recent confusion in this forum over where `scope` on the left applies to the `this` pointer or the one returned by the member function.

Kagamin just told me I needed to use `return` instead of `scope` to get things to work and I'm still not sure why.

The way I think about it is if you have a function that takes a pointer, any pointer, and either returns it or a pointer derived from it (dereferencing or indexing) that argument must be marked `return`. In your case it was a pointer derived from `this` so `return` must be applied to `this`.


Another way to think about it is this:

   S s;
   return &s;

We all know that is an error. The idea is to have a way to express that for:

    S s;
    return s.foo();

and:

    S s;
    return foo(&s);

so that the compiler knows that the return value of foo() is attached to the lifetime of s. Pretty much everything flows from that.

Would the guideline below be correct?

"Add scope to every non-template member function that isn't meant to escape this and add return to every non-template member function that returns all or part of `this` by pointer or ref if you want the compiler to check that nothing gets escaped in @safe code."

Being a template doesn't make any difference, except that it will helpfully infer these things.

The reason I wrote "non-template" is precisely because attributes get inferred for templates and therefore it would be at best redundant to annotate.

What about the guideline being correct or not?


Also, since 'this' is passed by 'ref' to struct member functions, it cannot escape anyway with dip1000:

  struct S {
    int x;
    @safe ref int foo() { return x; }
  }

  dmd test -dip1000
test.d(4): Error: returning this.x escapes a reference to parameter this, perhaps annotate with return

Returning by ref is good, since it's a lot harder to escape it. Since variables can't be declared ref, I can't pass it to a ref global. However:

----------
struct S {
    int x;
    @safe int* foo() { return &x; }
}
----------

% dmd -o- -dip1000 foo.d
% echo $?
0

Oops:

----------
int* gPtr;
void main() {
    auto s = S(42);
    gPtr = s.foo;
}
----------

"Don't use pointers then!". Ok:

----------
int[] gSlice;
void main() {
    auto s = S([42]);
    gSlice = s.foo;
}

struct S {
    int[] x;
    @safe int[] foo() return { return x; }
}
----------

% dmd -o- -dip1000 bar.d
% echo $?
0

Oops. I can't say `int[] x;` since it doesn't apply to fields.

`scope` is for pointers, `ref` does not need further annotation.

I always forget this, it's confusing. It doesn't help that slices have pointers, so I guess `scope` is for them too?

And in a struct, `this` is a `ref`, yet `scope` on a member function applies to `this`.

Atila


Reply via email to