December 22, 2012
On 12/22/2012 02:44 AM, Walter Bright wrote:
> On 12/21/2012 12:44 AM, Timon Gehr wrote:
>> ... modulo the private symbol clash issue. For all I know it is
>> deliberate,
>> which is embarrassing. Other than obviously breaking modularity, it
>> severely
>> restricts the usefulness of symbol disambiguation (which it makes
>> necessary when
>> it should not be), because the disambiguating alias may introduce more
>> conflicts
>> even if it is private, all over the code base.
>
> The reason it is that way is to avoid having it behave gratuitously
> differently than how visibility works within classes and structs.

I do not get that. The problem is that private symbols clash with public symbols in different modules. class and struct members are not even liable to inter-module overloadset-overlapping, which is necessary for this to happen.

How it works within classes and structs only affects the exact contents of error messages anyway, right? (not accessible vs. not defined) I'd consider that a compiler implementation detail.

Furthermore, I do not think there can be any kind of justification for the current behaviour in the first place.
December 22, 2012
On Friday, December 21, 2012 14:25:28 Walter Bright wrote:
> On 12/21/2012 1:40 PM, Jonathan M Davis wrote:
> > I would point out that -w does exactly that thanks to conditional compilation and compile-time introspection.
> 
> I know, and there are threads here where I opposed warnings very strongly.

I tend to agree that warnings were a bad idea and that they should never have
been introduced, if nothing else, because I don't think that it's ever good
practice to leave warnings in your code, making them almost the same as errors
anyway. However, what every other compiler I have ever seen does is what the
-wi flag does - always print warnings but never have them affect compilation. If
we're going to have them, I would expect that that's how they would always
work (so, no -wi or -w flags would be required, and warnings would never affect
compilation). The -w flag just makes things worse, because of how it affects
what will and won't compile.

It may be too late to change it now, but if we could, I would think that it would be best to make -wi the default behavior and deprecate both -w and -wi. Then we'd function like pretty much every other compiler on the planet, and we wouldn't have issues with compiler flags affecting conditional compilation.

- Jonathan M Davis
December 22, 2012
On Friday, December 21, 2012 17:44:43 Walter Bright wrote:
> On 12/21/2012 12:44 AM, Timon Gehr wrote:
> > ... modulo the private symbol clash issue. For all I know it is
> > deliberate,
> > which is embarrassing. Other than obviously breaking modularity, it
> > severely restricts the usefulness of symbol disambiguation (which it
> > makes necessary when it should not be), because the disambiguating alias
> > may introduce more conflicts even if it is private, all over the code
> > base.
> 
> The reason it is that way is to avoid having it behave gratuitously differently than how visibility works within classes and structs.

??? I don't see anything here that would become different between user-defined types and modules.

All we're really asking for here is that inaccessible symbols not be put in overload sets. That way, you don't have problems where adding a private function to a module breaks existing code, because it clashes with a public symbol in another module when a third module imports both modules.  For instance, right now, private aliases are useless, because they're pretty much exactly the same as public aliases, because they introduce name clashes. There is _zero_ value as far as I can see in having private symbols in one module affect the symbols in another. private symbols should be implementation details and not affect the compilation of other modules.

I would expect it to be exactly the same with private member functions and UFCS. So, if a new private member function is added to a class or struct, and code was using a free function with UFCS with that type, the code wouldn't change behavior or otherwise break because of the conflicting function which was added. The private function _wouldn't_ conflict, because it's private.

So, I don't see anything different here about how private would be handled between free functions and structs/classes. It seems to me like it would be exactly the same rather than gratuitously different. And even if it _were_ somehow different, the current behavior makes it frustratingly easy to break code when simply changing the names of the private functions of a module - functions which are supposed to be implementation detalis, and I would think that the difference would be well worth it.

Given how much you abhor breaking users' code, putting inaccessible symbols in overload sets seems like a rather odd choice to me. I understand how it stems from C++, but C++ doesn't have module-level access modifiers, and it doesn't have UFCS. The result in D is far more fragile. It makes it way too easy to break other people's code.

- Jonathan M Davis
December 22, 2012
On Friday, December 21, 2012 22:12:31 David Nadlinger wrote:
> On Friday, 21 December 2012 at 20:33:47 UTC, Jonathan M Davis
> 
> wrote:
> > If we didn't have -w,
> > then we could use warnings for stuff which was probably but not
> > definitively
> > wrong and which was okay to force people to change […] But
> > because
> > of -w, you can't […]
> 
> I don't think this is a valid argument: GCC has a similar flag (-Werror) too that many people use – for eaxmple, Google build all their code with it enabled, and other companies probably just as well – but still the compiler has quite a number of "best practices" warnings, e.g. regarding operator precedence rules.

gcc also warns by default rather than not giving warnings at all, so the situation is a bit different. -w used to be the _only_ way to even get warnings with dmd. Also, you have to be _way_ more careful with stuff like that in D because of all of the conditional compilation and compile-time introspection that it does. Using -w can drastically change the semantics of your code. And in the case of unused variables, it would completely break Phobos, because so many traits legitimately use unused variables. If anything, I think that it makes having -w at all a big mistake, but we have it, and I very much doubt that it's going away.

- Jonathan M Davis
December 22, 2012
On Saturday, 22 December 2012 at 04:21:06 UTC, Jonathan M Davis wrote:
> I tend to agree that warnings were a bad idea and that they should never have
> been introduced, if nothing else, because I don't think that it's ever good
> practice to leave warnings in your code, making them almost the same as errors
> anyway.

That's exactly how I treat warnings as errors, so to me they may as well be errors. The *only* time I treat a warning not as an error, is when I'm quickly messing around testing something out, but in the end I don't want to see any warnings at all.

--rt
December 22, 2012
On 12/21/2012 6:55 PM, Timon Gehr wrote:
> How it works within classes and structs only affects the exact contents of error
> messages anyway, right? (not accessible vs. not defined) I'd consider that a
> compiler implementation detail.

No, it affects the list of candidates for function overloading.

December 22, 2012
Jonathan M Davis:

> And in the case of unused variables, it would completely break Phobos, because so many traits legitimately use unused variables.

Given how important is to spot unused variables in user code, then maybe some solution can be invented for library code that has legitimate uses of unused variables, like creating a built-in attribute to mark an unused variable that the compiler will not report as unused. Like @used, a bit like "used" function attribute of GCC:

> used
>     This attribute, attached to a function, means that code must be
>     emitted for the function even if it appears that the function is
>     not referenced. This is useful, for example, when the function
>     is referenced only in inline assembly.

Bye,
bearophile
December 22, 2012
On Saturday, December 22, 2012 07:54:06 bearophile wrote:
> Jonathan M Davis:
> > And in the case of unused variables, it would completely break Phobos, because so many traits legitimately use unused variables.
> 
> Given how important is to spot unused variables in user code, then maybe some solution can be invented for library code that has legitimate uses of unused variables, like creating a built-in attribute to mark an unused variable that the compiler will not report as unused. Like @used, a bit like "used" function

I think that unused variables fall squarely in the realm of a lint-like tool and that it's serious overkill to add something to the language to mark variables that appear to be unused as actually being used just so that the compiler can complain about unused variables. But I also disagree that unused variables are a big deal. Certainly, I'd prefer not to have unused variables in my code, because it's messy to have them, but generally the worst that they'll do is create slight overhead because of the cost of default initializing them. I certainly don't think that it's worth having the compiler complain about them - _especially_ if that means jumping through hoops to get to not complain about legitimate unused variables.

- Jonathan M Davis
December 22, 2012
On Friday, December 21, 2012 22:42:54 Walter Bright wrote:
> On 12/21/2012 6:55 PM, Timon Gehr wrote:
> > How it works within classes and structs only affects the exact contents of error messages anyway, right? (not accessible vs. not defined) I'd consider that a compiler implementation detail.
> 
> No, it affects the list of candidates for function overloading.

But we _want_ that. The fact that inaccessible functions are even considered in overload sets is horrible. That's precisely the problem. No inaccessible functions should be in overload sets. Otherwise, simply adding a private function to a module can break code elsewhere. I don't see _any_ benefit in having inaccessible functions be in overload sets. It's leaking implementation details outside of the scope that they're in and breaking code elsewhere when changes are made. What do you think is so desirable about having inaccessible functions in overload sets?

- Jonathan M Davis
December 22, 2012
On 12/21/2012 11:23 PM, Jonathan M Davis wrote:
> But we _want_ that. The fact that inaccessible functions are even considered
> in overload sets is horrible. That's precisely the problem. No inaccessible
> functions should be in overload sets. Otherwise, simply adding a private
> function to a module can break code elsewhere. I don't see _any_ benefit in
> having inaccessible functions be in overload sets. It's leaking implementation
> details outside of the scope that they're in and breaking code elsewhere when
> changes are made. What do you think is so desirable about having inaccessible
> functions in overload sets?


It's that way in C++ mainly so that it doesn't make the already complex overloading system even more so. And in 25 years of working with C++, I've never seen this make anyone's list of horrible things about C++.