www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - cannot take address of scope local in safe function

reply vit <vit vit.vit> writes:
Why I can take address of Foo variable but not Bar?

```d
//-dip1000

struct Foo{
     private double d;
}

struct Bar{
     private void* ptr;
}



void main() safe{
     ///this is OK:
     {
         scope Foo x;
         scope ptr = &x;
     }

     ///Error: cannot take address of `scope` local `x` in ` safe` 
function `main`:
     {
         scope Bar x;
         scope ptr = &x;
     }
}
```
Jun 13 2021
parent reply ag0aep6g <anonymous example.com> writes:
On Sunday, 13 June 2021 at 16:27:18 UTC, vit wrote:
 Why I can take address of Foo variable but not Bar?

 ```d
 //-dip1000

 struct Foo{
     private double d;
 }

 struct Bar{
     private void* ptr;
 }



 void main() safe{
     ///this is OK:
     {
         scope Foo x;
         scope ptr = &x;
     }

     ///Error: cannot take address of `scope` local `x` in 
 ` safe` function `main`:
     {
         scope Bar x;
         scope ptr = &x;
     }
 }
 ```
`scope` affects indirections (i.e. pointers). `Foo` doesn't contain any indirections, so `scope` doesn't mean anything for it. The compiler just ignores it. It's like you wrote `Foo x;` without `scope`. `Bar` does contain an indirection, so `scope` actually matters and you get the error.
Jun 13 2021
parent reply vit <vit vit.vit> writes:
On Sunday, 13 June 2021 at 17:18:46 UTC, ag0aep6g wrote:
 On Sunday, 13 June 2021 at 16:27:18 UTC, vit wrote:
 Why I can take address of Foo variable but not Bar?

 ```d
 //-dip1000

 struct Foo{
     private double d;
 }

 struct Bar{
     private void* ptr;
 }



 void main() safe{
     ///this is OK:
     {
         scope Foo x;
         scope ptr = &x;
     }

     ///Error: cannot take address of `scope` local `x` in 
 ` safe` function `main`:
     {
         scope Bar x;
         scope ptr = &x;
     }
 }
 ```
`scope` affects indirections (i.e. pointers). `Foo` doesn't contain any indirections, so `scope` doesn't mean anything for it. The compiler just ignores it. It's like you wrote `Foo x;` without `scope`. `Bar` does contain an indirection, so `scope` actually matters and you get the error.
Thanks. 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); } ```
Jun 13 2021
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Sunday, 13 June 2021 at 17:49:50 UTC, 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);
     }

 ```
Simply remove the `scope` annotation from `or` and from the destructor and it works: https://run.dlang.io/is/hElNYf Because `OutputRange` is a `struct`, it will still be allocated on the stack even if you don't annotate it as `scope`.
Jun 13 2021
prev sibling parent ag0aep6g <anonymous example.com> writes:
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.
Jun 14 2021