On 13.06.21 19:49, vit wrote:
Is possible create and use scope output range allocated on stack in
@safe code?
Example:
```d
//-dip1000
struct OutputRange{
private bool valid = true;
private void* ptr;
int count = 0;
void put(Val)(auto ref scope Val val){
assert(this.valid == true);
this.count += 1;
}
~this()scope pure nothrow @safe @nogc{
this.valid = false;
}
}
void main()@safe pure nothrow @nogc{
import std.algorithm : copy;
import std.range : only;
scope OutputRange or;
only(1, 2, 3, 4).copy(&or); ///Error: cannot take address of
`scope` local `or` in `@safe` function `main`
assert(or.count == 4);
}
```
You're trying to create a `scope` pointer that points to another `scope`
pointer. That's not supported. You can only have one level of `scope`.
The first level of `scope` is explicit in `scope OutputRange or;`. The
second level is implicit in `&or`, because the address of a local
variable is necessarily a `scope` pointer.
As it's written, the first level isn't actually needed in your code. So
maybe you can just remove `scope` from `or` be done. But let's assume
that it really is needed for some reason.
The second level you do need. Without it, the assert fails. But you
wouldn't need the pointer if `copy` took the argument by `ref`, because
`ref` has a sort of implied `scope` that can be combined with an actual
`scope` to give two levels of protection. So you could write your own
`copy` with a `ref` parameter.
Or you can just write out what `copy` does in `main`, sidestepping the
issue:
----
foreach (e; only(1, 2, 3, 4))
{
or.put(e);
}
----
None of this is ideal, of course.