digitalmars.D - New attribute to control references
- Loara (60/60) Apr 25 2022 I wrote a simple article about an extended `scope` attribute that
- Salih Dincer (8/15) Apr 25 2022 It sounds good!
- Loara (9/14) Apr 26 2022 Actually I haven't implemented it yet, since I don't know how to
- Loara (6/9) Apr 27 2022 Since adding new attributes to D language also increases the
- Dennis (20/27) Apr 27 2022 The first section notes that DIP1000's documentation is lacking,
I wrote a simple article about an extended `scope` attribute that manages pointers and types that contains indirections: https://github.com/Loara/Rethink_scope_in_D/blob/main/README.md I called this new attribute `rscope` (this is a temporary name, I'll change it in future in order to avoid misunderstandings), any variable or function parameter marked as `rscope` can be referenced only by other variables that are also `rscope`: ````d rscope int i = 1; int j = i; //ok, doesn't share references //ref int k = i; error: k holds a reference to i rscope ref int h = i; //ok, both rscope rscope int *ip = new int (3); //int *iq = ip; error: reference sharing int *ik = new int(*ip); //ok //rscope *ih = ik; error: ik is not rscope, see the link struct A{ int a; int *b; } rscope A a = {1, &i}; //ok, i rscope //A b = a; //error, A has indirections, a rscoped but b no ```` Also you can use labelled `rscope` in order to avoid to share references between two or more `rscope` variables: ````d rscope(A) int *a = ...; rscope(A) int *b = a;//ok //rscope(B) int *c = a; error: different rscope groups ```` Why and where use this new attribute? Everywhere you need to avoid references escape: - when dealing with unsafe casts: ````d class A{...} ... const A a = ... ... rscope{//every variable declared inside this block is automatically rscope A a_unsafe = cast(A) a; //now you can use a_unsafe inside this block ... } //Now any reference to a_unsafe should be expired ```` - inside a `synchronized` block: ````d shared int i; Mutex mutex; .... synchronized(mutex){ rscope{ rscope ref int i_ref = get_rscoped_ref!int(i); .... } } ```` If you think these features would be interesting I'll write a new DIP and propose it, so I'm waiting your feedbacks.
Apr 25 2022
On Monday, 25 April 2022 at 16:06:00 UTC, Loara wrote:I wrote a simple article about an extended `scope` attribute that manages pointers and types that contains indirections: https://github.com/Loara/Rethink_scope_in_D/blob/main/README.mdIt sounds good! I will definitely read it, but it should not stay in theory. Is there a way to try it? For example, with the UDA... On Monday, 25 April 2022 at 16:06:00 UTC, Loara wroteI called this new attribute `rscope` (this is a temporary name, I'll change it in future in order to avoid misunderstandings), any variable or function parameter marked as `rscope` can be referenced only by other variables that are also `rscope`:I think it makes a lot of sense! I think rscope here means (referenceScope)? SDB 79
Apr 25 2022
On Tuesday, 26 April 2022 at 00:16:23 UTC, Salih Dincer wrote:It sounds good! I will definitely read it, but it should not stay in theory. Is there a way to try it? For example, with the UDA...Actually I haven't implemented it yet, since I don't know how to scan functions body and expressions in order to test code. Nothing forbits us to implement a ` rscope` UDA but it'd be useless until the compiler checks the code. On Tuesday, 26 April 2022 at 00:16:23 UTC, Salih Dincer wrote:I think it makes a lot of sense! I think rscope here means (referenceScope)?A bit, since we're working with references the classical meaning of block scope is too restrictive since an object allocated via `new` can exist among different scopes.
Apr 26 2022
On Monday, 25 April 2022 at 16:06:00 UTC, Loara wrote:I wrote a simple article about an extended `scope` attribute that manages pointers and types that contains indirections: [...]Since adding new attributes to D language also increases the "attribute pollution" (even now for each new function you should usually add at least three attributes) I want to be sure that this feature would be useful for more than a few people, otherwise it's better to move to some more popular proposals.
Apr 27 2022
On Monday, 25 April 2022 at 16:06:00 UTC, Loara wrote:https://github.com/Loara/Rethink_scope_in_D/blob/main/README.mdThe first section notes that DIP1000's documentation is lacking, which is true and something I'm working on (see for example https://github.com/dlang/dlang.org/pull/3284). It then mentions the lack of transitive scope, a known limitation, but with a curious example: ```D scope int **b = stack_allocate!(int *)(); ``` How would that function return a non-dangling stack pointer?A simple solution could be force scope variables to be used only as scope function parameters (...) but in this way we've made set completely useless, why we have to define a set function if we can't use it to set a member?Indeed, that's how it currently works, so you can't assign `scope` variables to a class field because `scope` only applies to the class reference itself. You can make a `set` function for a struct by marking the `p` parameter `return scope`.So the scope attribute is not what the manual-memory managment fans are waiting [for]That's assuming the given examples are representative of actual code. They could be, but personally, I usually only manually manage flat arrays. I know the current `scope` storage class leaves some things to be desired, but I don't understand why you propose a completely new attribute. Can a 'transitive scope' extension also suffice?
Apr 27 2022
On Wednesday, 27 April 2022 at 14:58:12 UTC, Dennis wrote:It then mentions the lack of transitive scope, a known limitation, but with a curious example: ```D scope int **b = stack_allocate!(int *)(); ``` How would that function return a non-dangling stack pointer?It could initialize the stack allocated pointer to `null` if no argument is passed, but it could be also a ` trusted` function, this is not the point, the point is that with a not transitive `scope` it's still possible to transfer references to non `scope` pointers without explicit casts.I admit the `return scope` attribute is a bit esoteric for me, I need to study it better.A simple solution could be force scope variables to be used only as scope function parameters (...) but in this way we've made set completely useless, why we have to define a set function if we can't use it to set a member?Indeed, that's how it currently works, so you can't assign `scope` variables to a class field because `scope` only applies to the class reference itself. You can make a `set` function for a struct by marking the `p` parameter `return scope`.I know the current `scope` storage class leaves some things to be desired, but I don't understand why you propose a completely new attribute. Can a 'transitive scope' extension also suffice?Originally I wrote these articles in order to specify how to implement a transitive `scope` attribute, but this would be too restrictive if the primary scope of `scope` is to allow stack allocation of objects. A transitive scope is more appropriate for `synchronized` access to a `shared` variable that contains indirections rather than a stack allocated object. But these are only my personal opinions.
Apr 27 2022
On Wednesday, 27 April 2022 at 15:51:36 UTC, Loara wrote:this is not the point, the point is that with a not transitive `scope` it's still possible to transfer references to non `scope` pointers without explicit casts.I think it's unclear what the example is demonstrating then. If the point is "the lack of an error here shows a hole in` safe`" then that's incorrect, because a function `stack_allocate!int(1);` can't return a scope pointer, and if you changed the signature so it could, dip1000 wouldn't allow you to assign it to `*b`. If the point is "a transitive `scope` enables this pattern" then that's also incorrect, because you still can't actually implement `stack_allocate!int(1);`. If, like you just clarified, the point is simply "`scope` isn't transitive", then that's correct, but that doesn't explain why there's a need for improvement in that regard.A transitive scope is more appropriate for `synchronized` access to a `shared` variable that contains indirections rather than a stack allocated object.I've never thought about using `scope` in combination with shared data, but it's an interesting thing to consider.
Apr 27 2022
On Wednesday, 27 April 2022 at 17:12:04 UTC, Dennis wrote:On Wednesday, 27 April 2022 at 15:51:36 UTC, Loara wrote:That examples were written because I didn't understand many features about `scope` since the official documentation wasn't so clear. But once I focus on the `synchronized` access to `shared` data the initial purpose of these pages have changed and now them are no longer useful.this is not the point, the point is that with a not transitive `scope` it's still possible to transfer references to non `scope` pointers without explicit casts.I think it's unclear what the example is demonstrating then.Since I don't know if a transitive `scope` would be useful also for stack-allocated variables or not, I've chosen the `rscope` name only to distinguish it from the standard and not transitive `scope` attribute.A transitive scope is more appropriate for `synchronized` access to a `shared` variable that contains indirections rather than a stack allocated object.I've never thought about using `scope` in combination with shared data, but it's an interesting thing to consider.
Apr 27 2022