Thread overview
[Issue 19752] dip1000 isn't @safe if struct contains a slice
Mar 19, 2019
ag0aep6g
Mar 19, 2019
Meta
Mar 20, 2019
Atila Neves
May 24, 2019
Radu Racariu
Mar 04, 2020
Walter Bright
Mar 04, 2020
Walter Bright
March 19, 2019
https://issues.dlang.org/show_bug.cgi?id=19752

ag0aep6g <ag0aep6g@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ag0aep6g@gmail.com

--- Comment #1 from ag0aep6g <ag0aep6g@gmail.com> ---
This seems to come down to `ref` parameters. `this` is a `ref` parameter, right?

This works:

    struct Container1
    {
        int* ints;
    }
    Container1* range1(return scope Container1* that) @safe
    {
        return that; /* accepted */
    }

This doesn't:

    struct Container2
    {
        int* ints;
    }
    Container2* range2(return scope ref Container2 that) @safe
    {
        return &that; /* Error: cannot take address of scope parameter that */
    }

As far as I see, the two should be same to DIP 1000.

--
March 19, 2019
https://issues.dlang.org/show_bug.cgi?id=19752

Meta <monkeyworks12@hotmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monkeyworks12@hotmail.com

--- Comment #2 from Meta <monkeyworks12@hotmail.com> ---
I believe this is because adding a slice member to Container makes it a type with indirections, whereas it was not before. DIP1000 only applies to types with indirections. If you were to add an int member to Container instead, the code would still compile as adding an int member to Container does not make it a type with indirections.

--
March 20, 2019
https://issues.dlang.org/show_bug.cgi?id=19752

--- Comment #3 from Atila Neves <atila.neves@gmail.com> ---
> I believe this is because adding a slice member to Container makes it a type with indirections, whereas it was not before. DIP1000 only applies to types with indirections.

In either case, `Range` is a type with an indirection, and `this` is an indirection itself, so the error message that "cannot take the address of a scope parameter this is @safe function range" makes no sense. The function is deliberately `return scope` so that the lifetime of the return value is tied to `this` and shouldn't be able to outlive it.

--
May 24, 2019
https://issues.dlang.org/show_bug.cgi?id=19752

Radu Racariu <radu.racariu@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |safe
                 CC|                            |radu.racariu@gmail.com

--
March 04, 2020
https://issues.dlang.org/show_bug.cgi?id=19752

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
         Resolution|---                         |INVALID

--- Comment #4 from Walter Bright <bugzilla@digitalmars.com> ---
Let's do a little rewriting:

----
struct Range { Container *self; }

struct Container {
    int* p;

    static Range range(return scope ref Container c) @safe {
        return Range(&c);
    }
}
----

which produces the same error. More rewrites:

----
struct Range { Container *self; }

struct Container { int* p; }

Range range(return scope ref Container c) @safe {
    return Range(&c);
}
----

produces the same error. More:

----
struct Container { int* p; }

Container* range(return scope ref Container c) @safe {
    return &c;
}
----

produces the same error. More:

----
int** range(return scope ref int* c) @safe {
    return &c;
}
----

produces the same error:

Error: cannot take address of ref parameter c in @safe function range

Now, the return value is not `ref`, so the `return` applies to the `int*`, not the `ref`. But we're not returning the `int*`, we're returning the address of the `int*` and recall the `return` doesn't apply to that, hence the error.

--
March 04, 2020
https://issues.dlang.org/show_bug.cgi?id=19752

--- Comment #5 from Walter Bright <bugzilla@digitalmars.com> ---
The key to understanding perplexing examples is to ruthlessly rewrite them in terms of `int*` and plain functions. Get rid of slices, this references, structs, member functions, etc. which do nothing but obfuscate what is happening, as they are just fancier versions of int* and functions.

--