January 30, 2013
On Monday, 28 January 2013 at 17:05:38 UTC, Dicebot wrote:
> http://wiki.dlang.org/DIP22

I think your going to need to give some evidence to the problems with the current behavior.

"dlang.org states that "Private module members are equivalent to static declarations in C programs." but this is wrong, they have external linkage:"

And this results in people writing code that ...? Is there an example where you can break code in another module by changing something marked as private?

"Name clash between public and private symbols has also been stated as unneeded and useless feature"

I'd be for this change, I don't know why it is currently that way though.

"There is currently no way in D to mark symbols for internal linkage"

What would that give us?

"Compiler errors upon access to private symbol are changed from "%s is not accessible" to "undefined identifier %s""

That will just be confusing. You put the name of that symbol because you saw it, being told it is undefined is going to make you think the compiler is broken.
January 30, 2013
Case 1 (binary level, C + D):

----- sample.d -----
module sample;
private int func() { return 42; }
----------

----- oops.c -----
#include <stdio.h>

extern int _D6sample4funcFZi();

void* _Dmodule_ref = 0;
void* _D15TypeInfo_Struct6__vtblZ = 0;

void _Dmain() { }

int main()
{
    long value = _D6sample4funcFZi();
    printf("%ld\n", value);
    return 0;
}
----------

----- shell -----
$ dmd - c sample.d
$ gcc -c oops.c
$ gcc oops.o sample.o
./a.out
42
----------

This is valid code now and will break. Internal linkage is a binary-level encapsulation tool, contrary to language-level private. Not that when compiling sample.d dmd can't know if oops.c will actually link to func and make decision about internal linkage. Saying this is invalid code may severely limit language interconnection possibilities and something like injecting druntime.

Case 2 (pure D, language level):

----- sample.d -----
module sample;
private struct Hest
{
    int a, b;
}
public alias Hidden UseMe;
----------

----- oops.d -----
import sample;
import std.stdio;

void main()
{
    UseMe tmp;
    tmp.a = 42;
}
----------

Now suddenly changing Test definition may break code in oops.d and we need first to make sure Test is not referenced in public aliases or as function parameter or as public type member field etc. Again, this code itself is not only valid but quite idiomatic. Internal linkage provides strong guarantees that any change to symbol will affect only its module, with no special cases.

Case 3 (consistency):

I do insist on keeping class and module protection attribute consistent. Saying class privates are always accessible from other modules via tupleof & friends and module privates may be not is causing confusion for no real gain. Also it may break code if we have any means to enumerate module symbols via traits (do we? I don't know).
January 30, 2013
On Wednesday, 30 January 2013 at 03:54:53 UTC, deadalnix wrote:
> I have to support that.
>
> static have already quite a lot of different meaning in D, and adding yet a new one probably not a good idea. Especially when module level declaration are supposed to be static by default, so now they can be static static, which is clearly a bad idea.
>
> Is the usage of export have been considered here ? private declaration are static/private, unless defined export ? Does that work ?

Yes, Timons example has convinced me with no doubts. I never wanted to use static that much to be honest, just avoid introduction of new attribute.

Regarding private as internal by default - please look at those examples: http://forum.dlang.org/post/irrbdrxordjawkryvrub@forum.dlang.org If we force internal linkage of private unless marked as export, it will break code like in case 2 or require some weird mangling hacks like in C/C++. I do not feel that it is justified, as those 2 concepts are rather different anyway. But it may be an option, need to evaluate all consequences though.
January 30, 2013
On Wednesday, 30 January 2013 at 05:29:14 UTC, Jesse Phillips wrote:
> And this results in people writing code that ...? Is there an example where you can break code in another module by changing something marked as private?

Examples separated:
http://forum.dlang.org/post/irrbdrxordjawkryvrub@forum.dlang.org

> "There is currently no way in D to mark symbols for internal linkage"
>
> What would that give us?

Strong 100% guarantees changes to the symbol won't break anything but its module. Strong 100% guarantees to compiler that he can optimize away/change all internal code when doing separate compilation.

> "Compiler errors upon access to private symbol are changed from "%s is not accessible" to "undefined identifier %s""
>
> That will just be confusing. You put the name of that symbol because you saw it, being told it is undefined is going to make you think the compiler is broken.

That was the most uneasy part of proposal. I have been thinking for few hours about it, considering different options. In the end, I have decided that it is only confusing to one coming from C++ lax approach and for clean mind it should make perfect sense that private symbol is indistinguishable from non-existing one in regular user code - that is the point of encapsulation how I get it.

Also in case of denied access most likely you have put that symbol because of typo, not because you know it (why would you intentionally try to use symbol you already know is private?). And it exposes internal module details by an accident.

I am very open for more arguments though, it is a somewhat tricky change.
January 30, 2013
On Wednesday, 30 January 2013 at 09:42:01 UTC, Dicebot wrote:
> On Wednesday, 30 January 2013 at 05:29:14 UTC, Jesse Phillips wrote:
>> And this results in people writing code that ...? Is there an example where you can break code in another module by changing something marked as private?
>
> Examples separated:
> http://forum.dlang.org/post/irrbdrxordjawkryvrub@forum.dlang.org
>

I understand the risk of breakage. But . . .

Is this code supposed to work in the first place ? I mean, the private function is not marked export, the language make no guarantee it will be accessible from C.

Additionally, does it make sense to prevent D from calling some piece of code, but still allow some external C code to do it ?

I think it is invalid code in the first place, and just happen to work right now.

case 2 is more tricky, but export isn't involved here.
January 30, 2013
On 01/30/2013 10:42 AM, Dicebot wrote:
> ...
> That was the most uneasy part of proposal. I have been thinking for few
> hours about it, considering different options. In the end, I have
> decided that it is only confusing to one coming from C++ lax approach
> and for clean mind it should make perfect sense that private symbol is
> indistinguishable from non-existing one in regular user code - that is
> the point of encapsulation how I get it.
> ...

As long as compile-time reflection cannot get hold of the error message, the more helpful diagnostic does not do any harm. (After all, the programmer might still be aware of the existence of the member, but missing that it is not accessible (yet) from the module he/she is currently working on.)
January 30, 2013
On 2013-01-30 10:57, deadalnix wrote:

> I understand the risk of breakage. But . . .

Not worth the breakage.

> Is this code supposed to work in the first place ? I mean, the private
> function is not marked export, the language make no guarantee it will be
> accessible from C.
>
> Additionally, does it make sense to prevent D from calling some piece of
> code, but still allow some external C code to do it ?
>
> I think it is invalid code in the first place, and just happen to work
> right now.
>
> case 2 is more tricky, but export isn't involved here.

It's not just accessing from C code. Due to D supporting separate compilation you can have the implementation of a private method in a separate object file.

-- 
/Jacob Carlborg
January 30, 2013
On Wednesday, 30 January 2013 at 12:02:46 UTC, Jacob Carlborg wrote:
> It's not just accessing from C code. Due to D supporting separate compilation you can have the implementation of a private method in a separate object file.

The code is in C in the example. But if you replace the C code by another D module, the exact same reasoning holds.

What point are you trying to make by raising that ? It seems completely irrelevant to me. Or I didn't inferred the part of the reasoning that was implied in your post. Please make it explicit.
January 30, 2013
On 2013-01-30 17:26, deadalnix wrote:

> The code is in C in the example. But if you replace the C code by
> another D module, the exact same reasoning holds.
>
> What point are you trying to make by raising that ? It seems completely
> irrelevant to me. Or I didn't inferred the part of the reasoning that
> was implied in your post. Please make it explicit.

If you have a public and a private function in the same module, it's possible to implement the two functions in two separate object files. The private function must then be available in the object file to link the program properly.

-- 
/Jacob Carlborg
January 31, 2013
On Wednesday, 30 January 2013 at 20:22:11 UTC, Jacob Carlborg wrote:
> If you have a public and a private function in the same module, it's possible to implement the two functions in two separate object files. The private function must then be available in the object file to link the program properly.

Ugh, how can you split module into two source/object files? Naive approach will result in linker error due to multiple definition of ModuleInfo. I did not know it was possible, would have been really cool to have.