Thread overview | |||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 22, 2019 Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
@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? Thanks for the help. Mike |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 02:29:49 UTC, Mike Franklin wrote:
> Possibility 1:
> Exhibit A should not emit an error
This looks like the right answer. I don't see any local reference escaping in the entire program.
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suleyman | On Sunday, 22 September 2019 at 02:52:17 UTC, Suleyman wrote:
> On Sunday, 22 September 2019 at 02:29:49 UTC, Mike Franklin wrote:
>> Possibility 1:
>> Exhibit A should not emit an error
>
> This looks like the right answer. I don't see any local reference escaping in the entire program.
This would involve inferring scope on non templates, which I believe would require modifying the specification.
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 02:29:49 UTC, Mike Franklin wrote:
> So, there's an inconsistency.
I don't think there is.
I think that taking a reference of a local variable should result in a scope T*.
In that case `&value` in `y ~= getValue1(&value);` should result in a scope int*.
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suleyman | On Sunday, 22 September 2019 at 02:52:17 UTC, Suleyman wrote:
> On Sunday, 22 September 2019 at 02:29:49 UTC, Mike Franklin wrote:
>> Possibility 1:
>> Exhibit A should not emit an error
>
> This looks like the right answer. I don't see any local reference escaping in the entire program.
When calling a function the compiler only looks at the function signature.
You can never pass a scope int* to a function accepting int*, regardless of whether the body of the function escapes it.
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sebastiaan Koppe |
On Sunday, 22 September 2019 at 07:01:42 UTC, Sebastiaan Koppe wrote:
> I think that taking a reference of a local variable should result in a scope T*.
>
> In that case `&value` in `y ~= getValue1(&value);` should result in a scope int*.
If that's the case then shouldn't Exhibit B (copied below for convenience) require getValue2` to be `int getValue2(scope ref int i)`? If not, what's the justification?
// Exhibit B
//--------------------------
int getValue2(ref int i)
{
return i;
}
int* foo2()
{
int value;
int[] y;
y ~= getValue2(value); // No error
return &y[0];
}
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On 22.09.19 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]; > } [...] > 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? As far as I understand, converting a `ref` to a pointer is still allowed with DIP 1000. So they should be handled the same. 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. */ } ---- |
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 07:54:12 UTC, Mike Franklin wrote:
>
> On Sunday, 22 September 2019 at 07:01:42 UTC, Sebastiaan Koppe wrote:
>> I think that taking a reference of a local variable should result in a scope T*.
>>
>> In that case `&value` in `y ~= getValue1(&value);` should result in a scope int*.
>
> If that's the case then shouldn't Exhibit B (copied below for convenience) require getValue2` to be `int getValue2(scope ref int i)`? If not, what's the justification?
scope only works on pointers.
---
@safe:
// Exhibit B
//--------------------------
struct P(T) {
T t;
}
alias Value1 = P!(int);
alias Value2 = P!(int*);
Value1 getValue1(ref Value1 v) { return v; }
Value2 getValue2(ref Value2 v) { return v; }
void foo2()
{
scope Value1 value1;
scope Value2 value2;
getValue1(value1); // No error
getValue2(value2); // Error: scope variable value2 assigned to non-scope parameter v calling onlineapp.getValue2
}
---
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sebastiaan Koppe | On Sunday, 22 September 2019 at 10:09:14 UTC, Sebastiaan Koppe wrote:
>> If that's the case then shouldn't Exhibit B (copied below for convenience) require getValue2` to be `int getValue2(scope ref int i)`? If not, what's the justification?
>
> scope only works on pointers.
>
> ---
> @safe:
>
> // Exhibit B
> //--------------------------
> struct P(T) {
> T t;
> }
>
> alias Value1 = P!(int);
> alias Value2 = P!(int*);
>
> Value1 getValue1(ref Value1 v) { return v; }
> Value2 getValue2(ref Value2 v) { return v; }
>
> void foo2()
> {
> scope Value1 value1;
> scope Value2 value2;
> getValue1(value1); // No error
> getValue2(value2); // Error: scope variable value2 assigned to non-scope parameter v calling onlineapp.getValue2
> }
> ---
I wouldn't say that `scope` only works for pointers, but rather `scope` only works for references (i.e. pointers and `ref` types). The issue is that `ref int i` behaves differently than `int* i`. I understand that scope doesn't make any sense for something like `int i` because it's not a "reference type" (for lack of a better term).
|
September 22, 2019 Re: Understanding DIP 1000 semantics -- Where's the bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Franklin | On Sunday, 22 September 2019 at 10:24:39 UTC, Mike Franklin wrote:
> I wouldn't say that `scope` only works for pointers, but rather `scope` only works for references (i.e. pointers and `ref` types). The issue is that `ref int i` behaves differently than `int* i`. I understand that scope doesn't make any sense for something like `int i` because it's not a "reference type" (for lack of a better term).
I know that an argument passed to a `ref int i` parameter is implemented with a pointer. And you would expect dip1000 to apply there as well, but the underlying type is still `int`, and scope only works on pointers.
Don't get me wrong, I rather see this work with value types as well, but this is how it currently works.
|
Copyright © 1999-2021 by the D Language Foundation