On 31.08.20 06:24, outlandkarasu wrote:
I thought that I cannot make non-scope `ref` parameters from `scope` array references.
But I found It allowed currently.
[...]
enum Currency : string {
     USD = "USD", EUR = "EUR", GBP = "GBP", JPY = "JPY",
}

struct Instrument {
     Currency bid;
     Currency ask;
}

struct Price {
     Instrument instrument;
     ulong value;
}
[...]
     void update(scope const(Price)[] prices) scope
     {
         foreach (price; prices)
         {
             update(price);
         }
     }

    // I thought price parameter need `scope` when called by scoped array elements.
     // But it can remove `scope` attribute.
     void update( /* scope */ ref const(Price) price) scope
     {
         if (minPrice.isNull || price.value < minPrice.get.value)
         {
             minPrice = price;
         }
     }

`ref` kind of implies `scope` [1]. You don't need to type it out. When you do type out `scope ref const(Price)`, the `scope` actually doesn't apply to the `ref` but to the pointers in `Price` (whereas the `scope` in `scope const(Price)[]` applies to the pointer of the array).

So you don't need `scope` on the `price` parameter because you're taking it as a `ref`. You would need `scope` if you were taking it as a pointer (`scope const(Price)* price`).

By the way, semantically there isn't any reason to take `price` as either `ref` or pointer. You can just as well take it by value, since you're making a copy of it anyway with `minPrice = price` (and you also make a copy earlier with `foreach (price; prices)`).

[...]
I also found a worried point that I can take non-scope pointer from non-scope `ref` parameter in DMV v2.093.1.

--------
class MinPointerRecorder
{
@nogc nothrow pure @safe:

     void update(scope const(Price)[] prices) scope
     {
         foreach (price; prices)
         {
             update(price);
         }
     }

     void update( /* scope */ ref const(Price) price) scope
     {
         if (!minPrice || price.value < minPrice.value)
         {
             // Is this DIP1000 BUG?
             // When without DIP1000, reported compile error.
             // Error: cannot take address of parameter price
             minPrice = &price;
         }
     }

     const(Price)* minPrice;
}
--------

Definitely a bug, yes. Reduced test case:

----
class MinPointerRecorder
{
    int* minPrice;
    void update(ref int price) @safe
    {
        minPrice = &price; /* Should not compile. */
    }
}

void main() @safe
{
    auto r = new MinPointerRecorder;
    () { int mp = 42; r.update(mp); } ();
    () { ulong[1000] stomp = 13; } ();
    import std.stdio: writeln;
    writeln(*r.minPrice); /* Prints "13". */
}
----

I don't think this is in Bugzilla yet. Please file an issue. Or let me know if you want me to do it.

https://issues.dlang.org




[1] I'm not exactly sure how it works. As far as I know, it's not documented anywhere.

Reply via email to