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.