www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - safe by default

reply Jacob Shtokolov <jacob.100205 gmail.com> writes:
Hi folks,

I know there were a lot of discussions on this topic, and it is 
understandable that due to historical reasons the D language is 
designed with C/C++ interop in mind, so it means that there is no 
 safe by default.

However, I also see a lot of people who want this feature, and I 
personally think that it would be great to have it, because it 
would save a lot of time by marking all functions as  safe by 
default, if it needs to.

It is also understandable that it's not possible to change this 
behavior today, because of compatibility. That's true and that's 
OK to be honest, nothing wrong with it.

I'm still learning D, so please accept my apologies if I don't 
see the whole picture, and if the question is obvious in some 
way, but I'd like to ask:

Is it possible to introduce a new parameter/flag to the compiler, 
to force all functions be  safe by default on a per-module basis?

For example:

```
module mymodule;

pragma(safe);

class Foo {
     // Already marked as  safe by "pragma(safe)"
     void bar() {
         ...
     }
}

//  safe by default
void fooBar() {
     ...
}
```

The same could be done to  nogc and maybe other attributes.

I know that probably I'm not the first guy who proposing that, 
but to be honest, I didn't find any fresh discussion about it, so 
just decided to ask here.

Thanks!
Jun 16 2018
next sibling parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov wrote:
 Is it possible to introduce a new parameter/flag to the 
 compiler, to force all functions be  safe by default on a 
 per-module basis?

 For example:

 ```
 module mymodule;

 pragma(safe);
We already have that, and with even shorter syntax: ``` module mymodule; safe: [...] ``` :-)
Jun 16 2018
parent reply Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Saturday, 16 June 2018 at 13:57:48 UTC, Bastiaan Veelo wrote:
 On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov 
 wrote:
 Is it possible to introduce a new parameter/flag to the 
 compiler, to force all functions be  safe by default on a 
 per-module basis?

 For example:

 ```
 module mymodule;

 pragma(safe);
We already have that, and with even shorter syntax: ``` module mymodule; safe: [...] ``` :-)
OMG! Didn't know that! xD Thank you Bastiaan!
Jun 16 2018
next sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Saturday, 16 June 2018 at 14:02:36 UTC, Jacob Shtokolov wrote:
 On Saturday, 16 June 2018 at 13:57:48 UTC, Bastiaan Veelo wrote:
 On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov 
 wrote:
 Is it possible to introduce a new parameter/flag to the 
 compiler, to force all functions be  safe by default on a 
 per-module basis?

 For example:

 ```
 module mymodule;

 pragma(safe);
We already have that, and with even shorter syntax: ``` module mymodule; safe: [...] ``` :-)
OMG! Didn't know that! xD Thank you Bastiaan!
You're welcome! It could have been better documented probably, because I was just looking for it and still cannot find it. I remember having seen it so I'm quite sure it is in there somewhere. At least it could have been in https://dlang.org/articles/safed.html. Here is one reference from the forum: https://forum.dlang.org/post/nj73gp$1q3k$1 digitalmars.com Ah, found it, at the very top of https://dlang.org/spec/attribute.html Yeah, it can be made more obvious.
Jun 16 2018
prev sibling next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 14:02:36 Jacob Shtokolov via Digitalmars-d wrote:
 On Saturday, 16 June 2018 at 13:57:48 UTC, Bastiaan Veelo wrote:
 On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov

 wrote:
 Is it possible to introduce a new parameter/flag to the
 compiler, to force all functions be  safe by default on a
 per-module basis?

 For example:

 ```
 module mymodule;

 pragma(safe);
We already have that, and with even shorter syntax: ``` module mymodule; safe: [...] ``` :-)
OMG! Didn't know that! xD Thank you Bastiaan!
I would point out that in general, doing that with attributes is rather error-prone, because it's easy for folks reading the code to miss them, making it unclear that they're in effect, and because unfortunately most attributes cannot be reversed, mass-applying them like that can then cause problems down the line when you need the attribute to _not_ apply to a function. That being said, safe is pretty much the one with the least problems, because it's one of the ones that you can reverse by using system or trusted explicitly where needed. However, there is no way to turn attribute inferrence back on, so putting safe at the top of a module that has templated functions where the safeness really needs to be inferred based on the template arguments can be a problem (though it's not as big a problem as putting trusted at the top of the module, since at least with safe, it just means that you'd end up with templates that don't compile when they would have been inferred as system, whereas with trusted, you'd potentially be hiding memory-safety bugs). So, while putting safe at the top of the module may very well be your best choice, be aware that mass-applying attributes like that _can_ cause problems. - Jonathan M Davis
Jun 16 2018
parent reply Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Saturday, 16 June 2018 at 17:46:56 UTC, Jonathan M Davis wrote:
 I would point out that in general, doing that with attributes 
 is rather error-prone, because it's easy for folks reading the 
 code to miss them, making it unclear that they're in effect, 
 and because unfortunately most attributes cannot be reversed, 
 mass-applying them like that can then cause problems down the 
 line when you need the attribute to _not_ apply to a function.

 That being said,  safe is pretty much the one with the least 
 problems, because it's one of the ones that you can reverse by 
 using  system or  trusted explicitly where needed. However, 
 there is no way to turn attribute inferrence back on, so 
 putting  safe at the top of a module that has templated 
 functions where the  safeness really needs to be inferred based 
 on the template arguments can be a problem (though it's not as 
 big a problem as putting  trusted at the top of the module, 
 since at least with  safe, it just means that you'd end up with 
 templates that don't compile when they would have been inferred 
 as  system, whereas with  trusted, you'd potentially be hiding 
 memory-safety bugs).

 So, while putting  safe at the top of the module may very well 
 be your best choice, be aware that mass-applying attributes 
 like that _can_ cause problems.

 - Jonathan M Davis
Thanks Jonathan! The case with templated functions indeed is not obvious.
 doing that with attributes is rather error-prone, because it's 
 easy for folks reading the code to miss them, making it unclear 
 that they're in effect, and because unfortunately most 
 attributes cannot be reversed, mass-applying them like that can 
 then cause problems down the line when you need the attribute 
 to _not_ apply to a function.
I completely agree with the second point - if we can't reverse these attributes in random places, the feature doesn't make sense at all. The first point, however, looks arguable to me. So I would say that it strongly depends on the task: for example, in web development there is absolutely no need to use pointers and other unsafe features until you really need them. In this case it's better to force safety for all functions by default, and it would be hard to do if we need to mark every single function as safe (not that hard of course, but very unpleasant).
Jun 16 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 21:08:27 Jacob Shtokolov via Digitalmars-d wrote:
 On Saturday, 16 June 2018 at 17:46:56 UTC, Jonathan M Davis wrote:
 doing that with attributes is rather error-prone, because it's
 easy for folks reading the code to miss them, making it unclear
 that they're in effect, and because unfortunately most
 attributes cannot be reversed, mass-applying them like that can
 then cause problems down the line when you need the attribute
 to _not_ apply to a function.
I completely agree with the second point - if we can't reverse these attributes in random places, the feature doesn't make sense at all. The first point, however, looks arguable to me. So I would say that it strongly depends on the task: for example, in web development there is absolutely no need to use pointers and other unsafe features until you really need them. In this case it's better to force safety for all functions by default, and it would be hard to do if we need to mark every single function as safe (not that hard of course, but very unpleasant).
The problem isn't whether changing the default is desirable. It's the fact that it's not at all obvious to anyone reading the code that that's what's happening - especially when you're dealing with stuff like github pull requests, where you're looking at a diff of the code and don't see the top of the file as part of the diff. This problem has popped up several times in druntime and Phobos where an attribute was mass-applied to a module or a struct, and it's caused varying levels of problems. Sometimes, it just means that an attribute ends up being applied locally in addition to being mass-applied, but in other cases, it's resulted in folks outright misunderstanding an aspect of the code that relates to the attribute that was mass-applied. Personally, I think that it's just plain bad practice to mass-apply attributes precisely because it causes confusion about the code. And I'd say the same even if all attributes were reversible. Being able to do something like pure(false) would definitely be useful with mass-applied attributes, but it wouldn't fix the maintenance problems that come from applying attributes in a completely different part of the file from the function being affected. So, while you're certainly free to mass-apply safe (or any other attribute) if you think that that will improve your code, I'd advise against it. - Jonathan M Davis
Jun 16 2018
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/16/18 10:02 AM, Jacob Shtokolov wrote:
 On Saturday, 16 June 2018 at 13:57:48 UTC, Bastiaan Veelo wrote:
 On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov wrote:
 Is it possible to introduce a new parameter/flag to the compiler, to 
 force all functions be  safe by default on a per-module basis?

 For example:

 ```
 module mymodule;

 pragma(safe);
We already have that, and with even shorter syntax: ``` module mymodule; safe: [...] ``` :-)
OMG! Didn't know that! xD Thank you Bastiaan!
I would just caution that this does not affect member functions, only module-level functions. You have to repeat the safe: inside any structs or classes as well. -Steve
Jun 16 2018
parent reply Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Saturday, 16 June 2018 at 18:47:10 UTC, Steven Schveighoffer 
wrote:
 I would just caution that this does not affect member 
 functions, only module-level functions. You have to repeat the 
  safe: inside any structs or classes as well.
Just tried that and it works very well (throws compilation errors): https://gist.github.com/run-dlang/ba59bcca4464d875f95f975d13bebe88 It seems that it works even for member functions! But still not sure about anonymous functions and delegates.
Jun 16 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/16/18 4:27 PM, Jacob Shtokolov wrote:
 On Saturday, 16 June 2018 at 18:47:10 UTC, Steven Schveighoffer wrote:
 I would just caution that this does not affect member functions, only 
 module-level functions. You have to repeat the  safe: inside any 
 structs or classes as well.
Just tried that and it works very well (throws compilation errors): https://gist.github.com/run-dlang/ba59bcca4464d875f95f975d13bebe88 It seems that it works even for member functions! But still not sure about anonymous functions and delegates.
Hm... interesting! I guess for safe it works, but other attributes (nothrow, pure), it doesn't. I assumed all the attributes behaved the same, but apparently not. -Steve
Jun 17 2018
prev sibling parent Mike Franklin <slavo5150 yahoo.com> writes:
On Saturday, 16 June 2018 at 13:52:37 UTC, Jacob Shtokolov wrote:

 Is it possible to introduce a new parameter/flag to the 
 compiler, to force all functions be  safe by default on a 
 per-module basis?
Forgive me if you're already aware of this, but to ensure your entire program is ` safe` (assuming it's single threaded) you only need to attribute `main` with ` safe`. This is because ` safe` functions cannot call unsafe functions and will emit a compiler error if attempting to do so. You still may need to attribute called functions with ` safe` or ` trusted` as necessary, and as others have already explained, but your program will enforce ` safe`ty simply by attributing `main`. Mike
Jun 17 2018