Is @safe still a work-in-progress?
Atila Neves
atila.neves at gmail.com
Thu Aug 23 13:10:17 UTC 2018
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
More information about the Digitalmars-d
mailing list