"default" keyword as function attribute

2016-03-19 Thread Jakob Ovrum via Digitalmars-d
We often repeat advice to put `@safe:`, or some other function 
attribute, at the top of your modules to apply the attribute en 
masse.


In practice this quickly becomes infeasible. Sooner or later, a 
generic function is introduced to idiomatic D modules, and many 
of them, perhaps most of them, are more general when attribute 
inference is used. Any explicit attribute application disables 
inference of that attribute. In my experience this is by far the 
most common reason that blanket application of attributes is 
impractical.


A recent example is this Phobos PR[1] which cannot apply `@safe` 
module-wide because the module contains generic functions where 
attribute inference is desirable. In this particular case it 
could be avoided by defining those generic functions before 
declaring `@safe:`, but this is at best unintuitive organization 
of code, and at worst highly intrusive when the generic function 
is a member function as it affects the whole type. It would also 
affect generated documentation with the current state of our 
tools.


DIP 79[2] suggests a number of possible language amendments that 
would help with this problem. The @attribute(expression>) syntax has support from (and was originally proposed 
by?) Andrei, but it doesn't really help with the attribute 
inference problem so I think we should consider it a separate 
issue.


It suggests "default" as a possible function attribute which 
negates previously applied attributes, which seems like it would 
solve the problem with minimal change to the language. Maybe 
there is a better way, or maybe we should move forward with it. 
What do you think?


Fixing this problem would encourage attribute proliferation while 
facilitating correct use of attribute inference.


[1] https://github.com/D-Programming-Language/phobos/pull/4082
[2] http://wiki.dlang.org/DIP79


Re: "default" keyword as function attribute

2016-03-19 Thread Jakob Ovrum via Digitalmars-d

On Saturday, 19 March 2016 at 14:55:00 UTC, Jakob Ovrum wrote:
Maybe there is a better way, or maybe we should move forward 
with it.


Maybe an alternative would be to simply ignore explicit 
attributes on templated functions, or at least ignore attributes 
on them applied with `attr:` or `attr { … }`. This could be a 
problem for `@trusted`.




Re: "default" keyword as function attribute

2016-03-19 Thread ZombineDev via Digitalmars-d

On Saturday, 19 March 2016 at 15:09:00 UTC, Jakob Ovrum wrote:

On Saturday, 19 March 2016 at 14:55:00 UTC, Jakob Ovrum wrote:
Maybe there is a better way, or maybe we should move forward 
with it.


Maybe an alternative would be to simply ignore explicit 
attributes on templated functions, or at least ignore 
attributes on them applied with `attr:` or `attr { … }`. This 
could be a problem for `@trusted`.


+ 1
This seams very reasonable. When writing templates one should 
almost always rely on attribute inference.


As for negation of attributes, I also support the approved by 
Andrei syntax:

final(false), @nogc(useGC == AllocateGC.no), etc.


Re: "default" keyword as function attribute

2016-03-19 Thread jmh530 via Digitalmars-d

On Saturday, 19 March 2016 at 15:09:00 UTC, Jakob Ovrum wrote:
Maybe an alternative would be to simply ignore explicit 
attributes on templated functions


That seems like a risky proposition. What if you mark some 
templates nogc to prevent inference on that. Then a future change 
causes an allocation. I would want to be notified.


Re: "default" keyword as function attribute

2016-03-19 Thread Jakob Ovrum via Digitalmars-d

On Saturday, 19 March 2016 at 18:15:54 UTC, jmh530 wrote:

On Saturday, 19 March 2016 at 15:09:00 UTC, Jakob Ovrum wrote:
Maybe an alternative would be to simply ignore explicit 
attributes on templated functions


That seems like a risky proposition. What if you mark some 
templates nogc to prevent inference on that. Then a future 
change causes an allocation. I would want to be notified.


Right. Any @nogc caller code would cease to compile, but maybe 
the generic function is the entry point to a @nogc subportion of 
the program.


As for the `default` approach, if we designed it to work with 
explicit attributes, like so:

---
@safe:
void foo();
void bar(T)(T t) default @nogc; // Infer pure, nothrow and @safe 
but require @nogc

---
Then `default` wouldn't have that problem.



Re: "default" keyword as function attribute

2016-03-19 Thread tsbockman via Digitalmars-d

On Saturday, 19 March 2016 at 15:09:00 UTC, Jakob Ovrum wrote:
Maybe an alternative would be to simply ignore explicit 
attributes on templated functions, or at least ignore 
attributes on them applied with `attr:` or `attr { … }`. This 
could be a problem for `@trusted`.


Please, no. Bulk application of attributes is very useful for 
templates, just like for regular code.


Re: "default" keyword as function attribute

2016-03-19 Thread tsbockman via Digitalmars-d

On Saturday, 19 March 2016 at 18:39:54 UTC, Jakob Ovrum wrote:
As for the `default` approach, if we designed it to work with 
explicit attributes, like so:

---
@safe:
void foo();
void bar(T)(T t) default @nogc; // Infer pure, nothrow and 
@safe but require @nogc

---
Then `default` wouldn't have that problem.


This could be OK, but it should work for bulk annotations, as 
well:


@safe pure @nogc nothrow {
void foo();

default @nogc {
void bar();
void baz();
}
}

It's rather awkward, but better than what we have now.


Re: "default" keyword as function attribute

2016-03-21 Thread Jonathan M Davis via Digitalmars-d

On Saturday, 19 March 2016 at 14:55:00 UTC, Jakob Ovrum wrote:
We often repeat advice to put `@safe:`, or some other function 
attribute, at the top of your modules to apply the attribute en 
masse.


In practice this quickly becomes infeasible. Sooner or later, a 
generic function is introduced to idiomatic D modules, and many 
of them, perhaps most of them, are more general when attribute 
inference is used. Any explicit attribute application disables 
inference of that attribute. In my experience this is by far 
the most common reason that blanket application of attributes 
is impractical.


I'm not necessarily against an addition to the language that 
would make it easier to reset the attributes to their "defaults" 
when attribute: or attribute{} has been used, but I confess that 
in general, I'm inclined to think that folks should think twice 
before apply attributes en masse like that. It makes it _way_ too 
easy to miss that the attribute is being applied when it's 
somewhere else entirely in the file. As ugly as it is, in 
general, I think that it makes far more sense to be explicit 
about it and put @safe, nothrow, pure, etc. directly on the 
functions and not use : or {}.


Personally, I only ever do it with access levels, which should 
generally be grouped together anyway IMHO, and even then, 
sometimes it's confusing about whether something is public or 
private without digging around elsewhere in the file to figure 
out whether a particular section is public or private. With 
@safe, pure, nothrow, etc., it's even worse, because it doesn't 
usually make sense to group functions based on those attributes, 
and you often do have to change one of those attributes on a 
particular function. It also makes it easy to accidentally apply 
attributes to templated functions, which is obviously bad.


So, I'd honestly be inclined to argue that doing stuff like 
@safe: or pure: is bad practice.


- Jonathan M Davis


Re: "default" keyword as function attribute

2016-03-21 Thread Jakob Ovrum via Digitalmars-d

On Monday, 21 March 2016 at 22:58:35 UTC, Jonathan M Davis wrote:
I'm inclined to think that folks should think twice before 
apply attributes en masse like that.


Why?

It makes it _way_ too easy to miss that the attribute is being 
applied when it's somewhere else entirely in the file.


This isn't a problem for anything but @trusted.



Re: "default" keyword as function attribute

2016-03-21 Thread Jonathan M Davis via Digitalmars-d

On Tuesday, 22 March 2016 at 02:05:20 UTC, Jakob Ovrum wrote:
On Monday, 21 March 2016 at 22:58:35 UTC, Jonathan M Davis 
wrote:
I'm inclined to think that folks should think twice before 
apply attributes en masse like that.


Why?


It makes it harder to know which attributes are actually being 
applied to a function, and it makes it way easier to accidentally 
apply attributes to a function. By putting them on the functions 
directly, it's very clear exactly which attributes apply, and 
you're not going to accidentally apply them to anything. And that 
becomes more critical as the file is maintained, because while 
you may know about all of those blanketed attributes when you 
first write the file, you may not realize that they're there 
later, and even if you do, someone else working on that file may 
not realize it. We've run into this with Phobos PRs where someone 
does the wrong thing, because they don't realize that an 
attribute has been applied to en masse.


It makes it _way_ too easy to miss that the attribute is being 
applied when it's somewhere else entirely in the file.


This isn't a problem for anything but @trusted.


It's worse for @trusted, but it's a problem any attributes that 
are involved with attribute inference. By putting something like 
pure: or nothrow: in the file, you risk accidentally marking any 
function that uses attribute inference as having that attribute. 
And while the compiler will error out in many cases, if you're 
dealing with templates, it's far too easy to not catch the 
problem. Your unit tests may very well work perfectly fine with 
those attributes, whereas a different set of template arguments 
would fail to compile thanks to those accidentally applied 
attributes, and you won't catch it until you (or someone else 
using your code) tries to use that function with template 
arguments that don't work with those attributes.


Another area where it causes problems is inheritance. Which 
attributes go on a base class function affect derived classes, 
possibly putting restrictions on derived classes that you don't 
want them to have. By using blanket attributes, it becomes easy 
to accidentally mark virtual functions as pure, nothrow, etc. and 
have those unit tests work just fine but then end up with someone 
else being screwed when they go to use that class, because those 
accidental attributes conflict with what they're trying to do. We 
have enough problems with making the right choices about which 
attributes go on virtual functions without having problems with 
them being applied accidentally.


I can understand someone wanting to reduce the number of 
annotations that they need to put on declarations in D, but from 
what I've seen, blanket attributes are a maintenance problem, and 
I think that we're almost always far better off without them. You 
shouldn't have to search through the file to figure out which 
attributes apply to a function, otherwise you end up with an 
increase in the number of mistakes related to attributes, some of 
which will be quickly caught and many of which won't be.


- Jonathan M Davis