www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - why local variables cannot be ref?

reply Fanda Vacek <fanda.vacek gmail.com> writes:
Maybe I'm missing the thing, but I'm not able to declare local 
ref variable even if simple workaround exists. Is this preferred 
design pattern?

```
int main()
{
	int a = 1;
	//ref int b = a; // Error: variable `tst_ref.main.b` only 
parameters or `foreach` declarations can be `ref`
	ref int b() { return a; }
	b = 2;
	assert(a == 2);
	return 0;
}
```

Fanda
Nov 24 2019
next sibling parent reply Rumbu <rumbu rumbu.ro> writes:
On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote:
 Maybe I'm missing the thing, but I'm not able to declare local 
 ref variable even if simple workaround exists. Is this 
 preferred design pattern?

 ```
 int main()
 {
 	int a = 1;
 	//ref int b = a; // Error: variable `tst_ref.main.b` only 
 parameters or `foreach` declarations can be `ref`
 	ref int b() { return a; }
 	b = 2;
 	assert(a == 2);
 	return 0;
 }
 ```

 Fanda
in D, but you can use pointers like in: int* b = &a; *b = 2;
Nov 24 2019
parent reply Fanda Vacek <fanda.vacek gmail.com> writes:
On Monday, 25 November 2019 at 05:51:31 UTC, Rumbu wrote:
 On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote:
 Maybe I'm missing the thing, but I'm not able to declare local 
 ref variable even if simple workaround exists. Is this 
 preferred design pattern?

 ```
 int main()
 {
 	int a = 1;
 	//ref int b = a; // Error: variable `tst_ref.main.b` only 
 parameters or `foreach` declarations can be `ref`
 	ref int b() { return a; }
 	b = 2;
 	assert(a == 2);
 	return 0;
 }
 ```

 Fanda
variables in D, but you can use pointers like in: int* b = &a; *b = 2;
Thanks for answer, I'm coming from C++. But anyway, pointers are not allowed in safe code, so this is not always solution. Workaround exits even for safe code, so my question remains the same. What is a rationale for such a language design restriction, if it can be workarounded easily.
Nov 25 2019
next sibling parent reply rumbu <rumbu rumbu.ro> writes:
On Monday, 25 November 2019 at 08:07:50 UTC, Fanda Vacek wrote:

 Thanks for answer, I'm coming from C++. But anyway, pointers 
 are not allowed in  safe code, so this is not always solution. 
 Workaround exits even for  safe code, so my question remains 
 the same. What is a rationale for such a language design 
 restriction, if it can be workarounded easily.
Enjoy: https://forum.dlang.org/post/blgcfjqdhtusavlrgdjr forum.dlang.org
Nov 25 2019
parent rumbu <rumbu rumbu.ro> writes:
On Monday, 25 November 2019 at 08:20:59 UTC, rumbu wrote:
 On Monday, 25 November 2019 at 08:07:50 UTC, Fanda Vacek wrote:

 Thanks for answer, I'm coming from C++. But anyway, pointers 
 are not allowed in  safe code, so this is not always solution. 
 Workaround exits even for  safe code, so my question remains 
 the same. What is a rationale for such a language design 
 restriction, if it can be workarounded easily.
Enjoy: https://forum.dlang.org/post/blgcfjqdhtusavlrgdjr forum.dlang.org
sSorry, wrong link above. https://forum.dlang.org/thread/ruwapnhkuvozitefzplt forum.dlang.org?page=1
Nov 25 2019
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Nov 25, 2019 at 08:07:50AM +0000, Fanda Vacek via Digitalmars-d-learn
wrote:
[...]
 But anyway, pointers are not allowed in  safe code, so this is not
 always solution.
[...] This is incorrect. Pointers *are* allowed in safe code. Pointer *arithmetic* is not allowed. --T
Nov 25 2019
parent reply Fanda Vacek <fanda.vacek gmail.com> writes:
On Monday, 25 November 2019 at 08:32:53 UTC, H. S. Teoh wrote:
 On Mon, Nov 25, 2019 at 08:07:50AM +0000, Fanda Vacek via 
 Digitalmars-d-learn wrote: [...]
 But anyway, pointers are not allowed in  safe code, so this is 
 not always solution.
[...] This is incorrect. Pointers *are* allowed in safe code. Pointer *arithmetic* is not allowed. --T
void main() safe { int a = 1; int *b = &a; *b = 2; assert(a == 2); } does not compile for me with Error: cannot take address of local `a` in ` safe` function `main` so there must be more restrictions in safe code Fanda
Nov 25 2019
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Nov 25, 2019 at 08:39:08PM +0000, Fanda Vacek via Digitalmars-d-learn
wrote:
 On Monday, 25 November 2019 at 08:32:53 UTC, H. S. Teoh wrote:
 On Mon, Nov 25, 2019 at 08:07:50AM +0000, Fanda Vacek via
 Digitalmars-d-learn wrote: [...]
 But anyway, pointers are not allowed in  safe code, so this is not
 always solution.
[...] This is incorrect. Pointers *are* allowed in safe code. Pointer *arithmetic* is not allowed.
[...]
 void main()  safe
 {
 	int a = 1;
 	int *b = &a;
 	*b = 2;
 	assert(a == 2);
 }
 
 does not compile for me with Error: cannot take address of local `a`
 in ` safe` function `main`
 
 so there must be more restrictions in  safe code
Correct, taking the address of a local variable is not allowed because of the possibility of a dangling pointer if the pointer leaks past the end of the variable's scope. With -dip1000, though, it should be allowed as long as you're not leaking the pointer past the lifetime of the local. Taking the address of a global is perfectly fine in safe code, as is using a pointer to a heap-allocated object (as long as no pointer arithmetic is involved). T -- If you're not part of the solution, you're part of the precipitate.
Nov 25 2019
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, November 25, 2019 1:32:53 AM MST H. S. Teoh via Digitalmars-d-
learn wrote:
 On Mon, Nov 25, 2019 at 08:07:50AM +0000, Fanda Vacek via
 Digitalmars-d-learn wrote: [...]

 But anyway, pointers are not allowed in  safe code, so this is not
 always solution.
[...] This is incorrect. Pointers *are* allowed in safe code. Pointer *arithmetic* is not allowed.
That and taking the address of a local variable is system, though with -dip1000, it becomes safe by making the result scope, which restricts what you can do with it. And of course, trusted can be used where appropriate to make it so that system code can be used from safe code, though obviously, that means that it's up to the programmer to make sure that they verify that what the trusted code is doing is actually safe. Further, with regards to taking the address of a local variable being system, ref would be system for exactly the same reasons save for the fact that there are various restrictions in place to ensure that it can't be used in a manner which would allow the underlying pointer to exist longer than the address that it refers to. Allowing variables in general to be declared as ref instead of only allowing it in restricted circumstances such as function parameters and return types would put ref in the same system quagmire that exists with regards to taking the address of a local variable. By restricting ref, that problem is avoided, whereas pointers still allow for full freedom but in return, they require that certain operations that relate to them be system (like &, ++, and --). - Jonathan M Davis
Nov 25 2019
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote:
 Is this preferred design pattern?

 ```
 int main()
 {
 	int a = 1;
 	//ref int b = a; // Error: variable `tst_ref.main.b` only 
 parameters or `foreach` declarations can be `ref`
 	ref int b() { return a; }
 	b = 2;
 	assert(a == 2);
 	return 0;
 }
 ```

 Fanda
It's okay, but I'd prefer an alias, because your snippet uses the heap needlessly (it puts variable a into heap to make sure there will be no stack corruption if you pass a pointer to function b() outside the main() function)
Nov 25 2019
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 25.11.19 10:00, Dukc wrote:
 On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote:
 Is this preferred design pattern?

 ```
 int main()
 {
     int a = 1;
     //ref int b = a; // Error: variable `tst_ref.main.b` only 
 parameters or `foreach` declarations can be `ref`
     ref int b() { return a; }
     b = 2;
     assert(a == 2);
     return 0;
 }
 ```

 Fanda
It's okay, but I'd prefer an alias, because your snippet uses the heap needlessly (it puts variable a into heap to make sure there will be no stack corruption if you pass a pointer to function b() outside the main() function)
This is not true. You can annotate main with nogc.
Nov 25 2019
prev sibling parent Fanda Vacek <fanda.vacek gmail.com> writes:
On Monday, 25 November 2019 at 09:00:49 UTC, Dukc wrote:
 On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote:
 Is this preferred design pattern?

 ```
 int main()
 {
 	int a = 1;
 	//ref int b = a; // Error: variable `tst_ref.main.b` only 
 parameters or `foreach` declarations can be `ref`
 	ref int b() { return a; }
 	b = 2;
 	assert(a == 2);
 	return 0;
 }
 ```

 Fanda
It's okay, but I'd prefer an alias, because your snippet uses the heap needlessly (it puts variable a into heap to make sure there will be no stack corruption if you pass a pointer to function b() outside the main() function)
Yes alias can help, but my original need was like void main() safe { int[] a = [1, 2]; alias head = a[0]; head = 2; assert(a[0] == 2); } there the alias doesn't work Fanda
Nov 25 2019