September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On 2019-09-22 04:29, Mike Franklin wrote: > @safe: > > // Exhibit A > //-------------------------- > int getValue1(int* i) > { > return *i; > } > > int* foo1() > { > int value; > int[] y; > y ~= getValue1(&value); //Error: reference to local variable `value` assigned to non-scope parameter `i` calling `onlineapp.getValue1` > return &y[0]; > } > > // Exhibit B > //-------------------------- > int getValue2(ref int i) > { > return i; > } > > int* foo2() > { > int value; > int[] y; > y ~= getValue2(value); // No error > return &y[0]; > } > > // Exhibit C (Same as Exhibit A, but with `scope` attribute on `i`) > //-------------------------- > int getValue3(scope int* i) > { > return *i; > } > > int* foo3() > { > int value; > int[] y; > y ~= getValue3(&value); // No error > return &y[0]; > } > > Compile with `-preview=dip1000`. See it live at https://run.dlang.io/is/0zODCr > > So, there's an inconsistency. > > Possibility 1: > Exhibit A should not emit an error > > Possibility 2: > Exhibit B should require the `scope` attribute on `i` or emit an error if `foo2`. > > Which is it? Where's the bug? Shouldn't the compiler treat `int* i` and `ref i` consistently? I think this is working as intended. In Exhibit A, `i` is a pointer and may escape the function `getValue1`. Therefore it's not allowed to pass the address of a local variable to it. In Exhibit B, `i` is a reference and cannot escape the function `getValue2`. In Exhibit C, the `scope` annotation of `i` makes sure that `i` cannot escape the function `getValue3`. Therefore it's ok to pass the address of a local variable to it. -- /Jacob Carlborg |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Sunday, 22 September 2019 at 11:03:29 UTC, Jacob Carlborg wrote:
> In Exhibit B, `i` is a reference and cannot escape the function `getValue2`.
Ok, that is an interesting observation. If that's the case, then I don't see any reason to ever annotate a `ref` parameter with `scope`. In other words, for `ref` parameters `scope` is inferred (or implied). Do you agree with that?
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Sunday, 22 September 2019 at 11:03:29 UTC, Jacob Carlborg wrote: > In Exhibit B, `i` is a reference and cannot escape the function `getValue2`. Actually, ag0aep6g's demonstration at https://forum.dlang.org/post/qm7cib$2n07$1@digitalmars.com proves that statement false. Unless it is a bug in the compiler that one can convert a `ref` to a pointer in `@safe` code. |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 11:42:44 UTC, Mike Franklin wrote:
> On Sunday, 22 September 2019 at 11:03:29 UTC, Jacob Carlborg wrote:
>
>> In Exhibit B, `i` is a reference and cannot escape the function `getValue2`.
>
> Actually, ag0aep6g's demonstration at https://forum.dlang.org/post/qm7cib$2n07$1@digitalmars.com proves that statement false. Unless it is a bug in the compiler that one can convert a `ref` to a pointer in `@safe` code.
Yes. The compiler only looks at the signature when it is checking the call site of said function.
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On 2019-09-22 13:22, Mike Franklin wrote: > Ok, that is an interesting observation. If that's the case, then I don't see any reason to ever annotate a `ref` parameter with `scope`. In other words, for `ref` parameters `scope` is inferred (or implied). Do you agree with that? Yes. -- /Jacob Carlborg |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On 2019-09-22 13:42, Mike Franklin wrote: > Actually, ag0aep6g's demonstration at https://forum.dlang.org/post/qm7cib$2n07$1@digitalmars.com proves that statement false. Unless it is a bug in the compiler that one can convert a `ref` to a pointer in `@safe` code. That might be a bug in the compiler. Adding `scope` to the reference doesn't help. But with DIP1000, there's some documentation missing and I think only Walter knows how it should behave. -- /Jacob Carlborg |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Sunday, 22 September 2019 at 16:32:02 UTC, Jacob Carlborg wrote: > On 2019-09-22 13:22, Mike Franklin wrote: > >> Ok, that is an interesting observation. If that's the case, then I don't see any reason to ever annotate a `ref` parameter with `scope`. In other words, for `ref` parameters `scope` is inferred (or implied). Do you agree with that? > > Yes. According to DIP1000 (https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md#identity-function) `scope ref` is a thing, so I guess `scope` can't be inferred or implied for `ref`. I don't know. I think Walter is the only one that can clear this up. |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 17:01:59 UTC, Mike Franklin wrote: > On Sunday, 22 September 2019 at 16:32:02 UTC, Jacob Carlborg wrote: >> On 2019-09-22 13:22, Mike Franklin wrote: >> >>> Ok, that is an interesting observation. If that's the case, then I don't see any reason to ever annotate a `ref` parameter with `scope`. In other words, for `ref` parameters `scope` is inferred (or implied). Do you agree with that? >> >> Yes. > > According to DIP1000 (https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md#identity-function) `scope ref` is a thing, so I guess `scope` can't be inferred or implied for `ref`. > > I don't know. I think Walter is the only one that can clear this up. Yes, `scope ref` is definitely a thing. Compare the following. // Exhibit C @safe: struct A { int* ptr; } int* gptr; void foo(ref A a) { gptr = a.ptr; // error, can't leak borrowed a.ptr into global context } https://run.dlang.io/is/ZU780c // Exhibit D @safe: struct A { int* ptr; } int* gptr; void foo(scope ref A a) { gptr = a.ptr; // error, can't leak borrowed a.ptr into global context } https://run.dlang.io/is/ZU780c This was taken from the discussion at https://forum.dlang.org/post/twgsrfcolypurgylhizh@forum.dlang.org |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Sunday, 22 September 2019 at 08:49:14 UTC, ag0aep6g wrote: > Then it's possibility 2: `foo2` should error. Your code can easily be expanded to demonstrate memory corruption: > > ---- > @safe: > > immutable(int)* ip; > > // Exhibit B > //-------------------------- > int getValue2(ref immutable int i) > { > immutable int* my_ip = &i; > ip = my_ip; > return i; > } > > int* foo2() > { > immutable int value = 42; > int[] y; > y ~= getValue2(value); // No error > return &y[0]; > } > > void main() > { > auto p = foo2(); > import std.stdio; > writeln(*ip); /* Prints "42". */ > writeln(*ip); /* Prints garbage. An immutable value has changed. */ > } > ---- Interestingly, taking the address of a `ref` in `@safe` code is prevented, but only when compiling *without* -preview=dip1000. See https://run.dlang.io/is/GArFzk That's seems like a bug to me. |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On 2019-09-22 19:26, Mike Franklin wrote: > On Sunday, 22 September 2019 at 08:49:14 UTC, ag0aep6g wrote: > >> Then it's possibility 2: `foo2` should error. Your code can easily be expanded to demonstrate memory corruption: >> >> ---- >> @safe: >> >> immutable(int)* ip; >> >> // Exhibit B >> //-------------------------- >> int getValue2(ref immutable int i) >> { >> immutable int* my_ip = &i; >> ip = my_ip; >> return i; >> } >> >> int* foo2() >> { >> immutable int value = 42; >> int[] y; >> y ~= getValue2(value); // No error >> return &y[0]; >> } >> >> void main() >> { >> auto p = foo2(); >> import std.stdio; >> writeln(*ip); /* Prints "42". */ >> writeln(*ip); /* Prints garbage. An immutable value has changed. */ >> } >> ---- > > Interestingly, taking the address of a `ref` in `@safe` code is prevented, but only when compiling *without* -preview=dip1000. See https://run.dlang.io/is/GArFzk > > That's seems like a bug to me. With DIP1000 enabled the compiler can figure out that it is safe to take the address of `i` and assign it to `my_ip`. It seems to fail to recognize that assigning to `ip` is unsafe. Perhaps that requires data flow analysis. If you assign directly to `ip` it fails to compile. -- /Jacob Carlborg |
Copyright © 1999-2021 by the D Language Foundation