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.

Reply via email to