How do I copy struct having immutable pointer member when enabled DIP1000?
outlandkarasu
outland.karasu at gmail.com
Mon Aug 31 04:24:50 UTC 2020
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.
More information about the Digitalmars-d-learn
mailing list