Understanding DIP 1000 semantics -- Where's the bug?

ag0aep6g anonymous at example.com
Tue Sep 24 13:35:04 UTC 2019


On 24.09.19 10:05, Sebastiaan Koppe wrote:
> On Monday, 23 September 2019 at 20:50:30 UTC, ag0aep6g wrote:
[...]
>> Not really. When you do that, DMD rejects the `return` statement, not 
>> the assignment `p = foo(x);`.
> 
> But that is what you want right? You want it to error out.

Not at that point. Unless `ref` implies restrictions that pointers don't 
have, `foo` should compile.

> My reasoning is as follows, because dataflow analyses is missing, you 
> need to simplify the body of foo to `return &x`. Then the compilers 
> errors out saying you are escaping a reference and maybe you need to add 
> the return annotation. After you fix that the compiler errors out saying 
> "Error: address of variable x assigned to p with longer lifetime". Which 
> is exactly what we want.
> 
> Ergo, missing dataflow analyses.

Aside: Your reasoning is circular. You start and end with "dataflow 
analysis is missing".

When using a pointer instead of `ref`, the code is rejected as expected 
even with the more complex body:

----
@safe:

int* foo(int* x)
{
     int* a = x;
     return x;
}

void main() {
     int* p;
     {
         int x;
         p = foo(&x); /* error here */
     }
}
----

So it works just fine with pointers. But maybe `ref`s are intentionally 
treated differently from pointers. And maybe that means that they need 
more advanced dataflow analysis which isn't currently implemented. If 
that's so, it's a hole in -dip1000.

So I'm saying: Just treat `ref`s like pointers and the trouble 
disappears. I suspect that it's actually intended to work like that, and 
we're just looking at a good old bug.

>> It works as expected when you mark the parameter with `return`. This 
>> has nothing to do with missing flow analysis. It's just a bug.
> 
> I agree that it will be better to get the 2 errors the first time, but 
> is that a bug?

Memory corruption in @safe code is always a bug.

[...]
> 1) fp isn't `scope int*` so the function body compiles without errors;

Yup.

> 2) you cannot return a reference to a local, so the function `fr` errors 
> out correctly;

A `ref` parameter is significantly different from a true local. In the 
context of DIP 1000, it's more straight-forward to treat it like a pointer.

> 3) you cannot pass a reference to a local to a non-scope argument, so 
> fp(&x) errors out correctly;

Yup.

> 4) it is perfectly valid to pass a value to a ref parameter;

Not when we treat `ref` like the pointer that it really is.

Pretending that `ref` is anything but a pointer wearing a fancy hat just 
leads to headaches like the one we're experiencing right now.


More information about the Digitalmars-d mailing list