digitalmars.D.learn - cannot take address of scope local in safe function
- vit (23/23) Jun 13 2021 Why I can take address of Foo variable but not Bar?
- ag0aep6g (7/30) Jun 13 2021 `scope` affects indirections (i.e. pointers). `Foo` doesn't
- vit (28/65) Jun 13 2021 Thanks.
- Paul Backus (6/32) Jun 13 2021 Simply remove the `scope` annotation from `or` and from the
- ag0aep6g (23/60) Jun 14 2021 You're trying to create a `scope` pointer that points to another `scope`...
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
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
On Sunday, 13 June 2021 at 17:18:46 UTC, ag0aep6g wrote:On Sunday, 13 June 2021 at 16:27:18 UTC, vit wrote: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); } ```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
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
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