On Sunday, 30 August 2020 at 16:33:58 UTC, ag0aep6g wrote:
On 30.08.20 17:24, outlandkarasu wrote:
--------
enum Tag { tag = "tag" }
struct A { Tag tag; }
A createA() @safe
{
scope a = A(Tag.tag);
// Error: scope variable a may not be returned
return a;
// NG
// return A(a);
// return A(a.tag);
}
--------
[...]
I understand those errors are DIP1000 language design.
However I suppose that DIP1000 check can permit immutable
pointer in some cases.
If I understand correctly, your point is that an enum pointer
is guaranteed to refer to static data, so it could be exempt
from `scope` checks.
At a glance, that makes sense to me. But I guess one question
is whether it's possible to create an enum value that points to
the stack. A cast does the trick:
immutable char[1] c = 'e';
E e = cast(E) c[];
DMD accepts it as @safe, implying that the cast is valid and
that `e` is a safe value. If that is correct, then enum
pointers are actually not guaranteed to refer to static data.
They can just as well point to the stack. Consequently, an enum
pointer must be treated like a plain pointer. I.e., `scope`
must treat a `Tag` just like a plain `string`.
Is there a better workaround, practices or patterns?
In your example, you can just remove the `scope` annotation.
Why mark a local that you want to return with `scope`? Doesn't
make sense
But I guess your actual use case isn't as simple. Maybe you can
show a less reduced version of the code where simply removing
`scope` is not an option?
Thanks for your reply.
I thought that I cannot make non-scope `ref` parameters from
`scope` array references.
But I found It allowed currently.
My reduced version code is below;
--------
enum Currency : string {
USD = "USD", EUR = "EUR", GBP = "GBP", JPY = "JPY",
}
struct Instrument {
Currency bid;
Currency ask;
}
struct Price {
Instrument instrument;
ulong value;
}
class MinRecorder
{
@nogc nothrow pure @safe:
// prices from local scoped array buffers.
// I want to restrict prices reference to scope.
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;
}
}
Nullable!Price minPrice;
}
--------
full example:
https://run.dlang.io/is/wVbrwf
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;
}
--------
I also think about Flyweight pattern in D.
I expected simple struct that contains cached `immutable`
reference behaves a simple value type like primitive types.
But reference contained struct is not simple.
If I want a simple value type struct, the struct shouldn't be
contain any references also include static string or immutable
reference.