Jump to page: 1 24  
Page
Thread overview
Understanding DIP 1000 semantics -- Where's the bug?
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Suleyman
Sep 22, 2019
Max Haughton
Sep 22, 2019
Sebastiaan Koppe
Sep 22, 2019
Sebastiaan Koppe
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Sebastiaan Koppe
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Sebastiaan Koppe
Sep 22, 2019
ag0aep6g
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Jacob Carlborg
Sep 22, 2019
ag0aep6g
Sep 23, 2019
Olivier FAURE
Sep 23, 2019
Sebastiaan Koppe
Sep 23, 2019
Meta
Sep 23, 2019
Meta
Sep 23, 2019
Sebastiaan Koppe
Sep 23, 2019
ag0aep6g
Sep 24, 2019
Sebastiaan Koppe
Sep 24, 2019
ag0aep6g
Sep 24, 2019
Olivier FAURE
Sep 24, 2019
ag0aep6g
Sep 24, 2019
ag0aep6g
Sep 24, 2019
Sebastiaan Koppe
Sep 26, 2019
Walter Bright
Sep 26, 2019
Walter Bright
Sep 26, 2019
Sebastiaan Koppe
Sep 22, 2019
Jacob Carlborg
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Jacob Carlborg
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Mike Franklin
Sep 23, 2019
Olivier FAURE
Sep 26, 2019
Walter Bright
Sep 22, 2019
Mike Franklin
Sep 22, 2019
Sebastiaan Koppe
Sep 22, 2019
Jacob Carlborg
Sep 26, 2019
Walter Bright
September 22, 2019
@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
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
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
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
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
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
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
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
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
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.


« First   ‹ Prev
1 2 3 4