Why can't I give a function's return type the scope storage class?
ag0aep6g
anonymous at example.com
Tue Mar 19 16:11:27 UTC 2019
On 19.03.19 04:48, Meta wrote:
> My example code is a bit too long to post here, but it can be found at
> https://run.dlang.io/is/e6Lc15. The main crux of this issue is:
>
> @safe
> Queue!Data copyToQueue(DataRange data)
> {
> Queue!Data output;
> while (!data.empty)
> {
> auto d = data.front;
> data.popFront();
> import std.random: uniform;
> if (uniform(0, 100) < 50)
> {
> output.push(d);
> }
> }
> return output;
> }
>
> And the definition of Queue!T.push is:
>
> @safe
> void push(return scope T val) scope
> {
> ptr += 1;
> if (ptr >= store.length && ptr < size_t.max)
> {
> store.length = store.length == 0
> ? 8
> : store.length * growthFactor;
> }
> //FIXME: either I don't understand DIP1000
> //well enough, or this should compile
> //Workaround: surround it with an @trusted lambda
> store[ptr] = val;
> }
I think it boils down to the following.
This works:
struct Q
{
string s;
void push(return scope string v) scope @safe
{
this.s = v;
}
}
This doesn't:
struct Q
{
string[] s;
void push(return scope string v) scope @safe
{
this.s.length = this.s.length + 1;
this.s[$ - 1] = v;
}
}
The reason is that `scope` is not transitive. The array `this.s` is
`scope`, but an element like `this.s[$ - 1]` isn't. The compiler
considers the elements to have infinite lifetime.
Here's another example that illustrates this. When you've got a `scope
Q`, the compiler won't let you return `q.s`, but it doesn't mind you
returning an element of it:
struct Q
{
string[] s;
}
string[] f(scope Q q)
{
return q.s; /* Error: scope variable q may not be returned */
}
string g(scope Q q)
{
return q.s[0]; /* no error, the element is not `scope` */
}
More information about the Digitalmars-d
mailing list