Jump to page: 1 2
Thread overview
[Issue 24754] cannot take address of a member array in a ref foreach
Sep 13
Dennis
Sep 13
Dennis
Sep 13
Dennis
September 09
https://issues.dlang.org/show_bug.cgi?id=24754

Luís Ferreira <contact@lsferreira.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Hardware|x86_64                      |All
                 OS|Linux                       |All
           Severity|enhancement                 |normal

--
September 09
https://issues.dlang.org/show_bug.cgi?id=24754

Dominikus Dittes Scherkl <dominikus@scherkl.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |dominikus@scherkl.de
         Resolution|---                         |INVALID

--- Comment #1 from Dominikus Dittes Scherkl <dominikus@scherkl.de> ---
Pointers are not allowed in @safe functions at all. That's not a bug, it's a feature!

--
September 09
https://issues.dlang.org/show_bug.cgi?id=24754

Richard (Rikki) Andrew Cattermole <alphaglosined@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |accepts-invalid, safe
           Priority|P1                          |P3
             Status|RESOLVED                    |REOPENED
                 CC|                            |alphaglosined@gmail.com
         Resolution|INVALID                     |---

--- Comment #2 from Richard (Rikki) Andrew Cattermole <alphaglosined@gmail.com> ---
This might be a bug, DIP1000 should be catching this I think.

I checked, and with it turned on it did not catch it.

But yes, a pointer is allowed in @safe functions, including taking a pointer of currently.

--
September 09
https://issues.dlang.org/show_bug.cgi?id=24754

Nick Treleaven <nick@geany.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nick@geany.org

--- Comment #3 from Nick Treleaven <nick@geany.org> ---
> This might be a bug, DIP1000 should be catching this I think.

If `&e` is the address of an int inside the `Foo.foo` array, then that is fine so long as the array is null or GC allocated.

However, if Foo.foo is changed to `int[1] foo;`, it still won't error and it should:

```d
import std.stdio;

struct Foo
{
    int[1] foo;

    @safe
    int* foobar()
    {
        int* f;
        foreach(ref e; foo)
            f = &e; // escaping address of foo[0]
        return f;
    }
}

void main() @safe
{
    int* p;
    {
        Foo foo = Foo([1]);
        //writeln(&foo.foo[0]);
        p = foo.foobar();
    }
    p.writeln();
    (*p).writeln();
}
```

--
September 12
https://issues.dlang.org/show_bug.cgi?id=24754

--- Comment #4 from Luís Ferreira <contact@lsferreira.net> ---
> Pointers are not allowed in @safe functions at all.

What are you talking about? They are, its specified in the spec. 20.24.1. Safe Functions.

Please don't close tickets as invalid as you see them and just because you think they are invalid. It's not productive for anyone. Maybe someone else sympathize with the same problem, you might not have enough understanding of it, ask for elaboration, or present arguments against it...

---

> That's not a bug, it's a feature!

This is a bug, and an industry facing bug. Probably one of the reasons no one at industry use or rely on it (e.g. like people do in Rust), in practice, @safe, is because its buggy and have holes. Being restrictive at the point of not allowing pointers is not a real feature, if D didn't allow pointers. It would certainly make the feature even less adopted.

It's another question if we would discuss if D allows a subset of pointers only (like ref variables, or like Zig does, define the pointer semantic restrictions in the type), but that goes out of scope both from what is defined in spec and what we have today.

Also if pointers was the real problem, explain why this code compiles:

```
struct Foo
{
    int[] foo;

    @safe
    void foobar()
    {
        int* f;
        foreach(i; 0 .. foo.length)
            f = &foo[i];
    }
}

void main()
{
    Foo foo;
    foo.foobar();
}
```

It uses pointers, doesn't it?

--
September 12
https://issues.dlang.org/show_bug.cgi?id=24754

--- Comment #5 from Luís Ferreira <contact@lsferreira.net> ---
> If `&e` is the address of an int inside the `Foo.foo` array, then that is fine so long as the array is null or GC allocated.

Specification guarantees that only safe assignments are made, so, whatever is assigned to `foo`, unless its `= void` assignment, its safe to de-reference it, again, as long as the assignment is safe.

> However, if Foo.foo is changed to `int[1] foo;`, it still won't error and it should

The code you presented escapes variables. The code I presented doesn't escape anything beyond its own scope, which is conceptually not escaping. Escaping is defined via DIP1000, and I'm not expecting the code to compile when escaping without defining `return` attribute to the member function.

--
September 12
https://issues.dlang.org/show_bug.cgi?id=24754

--- Comment #6 from Luís Ferreira <contact@lsferreira.net> ---
> > However, if Foo.foo is changed to `int[1] foo;`, it still won't error and it should

Also the code you presented has a different type, even though trivially valid if you don't escape from within the function, which you do, so it doesn't apply to this particular issue.

---

For the frontend folks, just ease this from DIP1000 preview flag, it doesn't make sense to be within the flag.

--
September 12
https://issues.dlang.org/show_bug.cgi?id=24754

--- Comment #7 from Luís Ferreira <contact@lsferreira.net> ---
Funny enough, if you compile the initial code snippet with `-vcg-ast` (that yields incorrect D code, but you can understand how it converts it to), it pretty much converts it to something compatible like this, which is compilable:

```
struct Foo
{
        int[] foo;
        void foobar()
        {
                int* f = null;
                {
                        int[] __r2 = this.foo[];
                        ulong __key3 = 0LU;
                        for (; __key3 < __r2.length; __key3 += 1LU)
                        {
                                int* e = &__r2[__key3];
                                f = e;
                        }
                }
        }
}
```

--
September 12
https://issues.dlang.org/show_bug.cgi?id=24754

Luís Ferreira <contact@lsferreira.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|accepts-invalid             |rejects-valid

--
September 13
https://issues.dlang.org/show_bug.cgi?id=24754

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dkorpel@live.nl

--- Comment #8 from Dennis <dkorpel@live.nl> ---
Reduces to:

```D
void main() @safe
{
    foreach(ref e; new int[1])
        int* f = &e;
}
```

--
« First   ‹ Prev
1 2