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