August 01, 2018
On 8/1/2018 7:09 PM, Rubn wrote:
> On Wednesday, 1 August 2018 at 23:04:01 UTC, Walter Bright wrote:
>> An example of silent hijacking:
>>
>>    extern (C++, "ab") void foo(long); // original code
>>    ... lots of code ...
>>    extern (C++, "cd") void foo(int); // added later by intern, should have been
>>                                      // placed in another module
>>    ... a thousand lines later ...
>>    foo(0); // OOPS! now calling cd.foo() rather than ab.foo(), D sux
>>
>> You might say "nobody would ever write code like that." But that's like the C folks saying real C programmers won't write:
> 
> You can do that today, just remove the "extern(C++, ...)" part and you have the same issue. Why should C++ with namespaces be safer than just regular D ? I don't understand, if it is such a huge gigantic problem why didn't you do anything to solve this problem in regards to D then ?

The difference is those names are supposedly in different namespaces, given that the code is converted from C++:

    namespace ab { void foo(long); }
    ... lots of code ...
    namespace cd { void foo(int); }

where the foo()'s do not conflict with each other, and a user would reasonably expect that same behavior when translated to D.


If you *want* them in the same scope in D, you can do that with alias.
August 02, 2018
Am Wed, 01 Aug 2018 16:31:57 -0700 schrieb Walter Bright:

> On 7/31/2018 1:47 AM, Atila Neves wrote:
>> The only good way (I don't think the mixin template and struct
>> solutions count)
>> to link to any of that today would be to have one enormous D file with
>> _everything_ in it, including nested namespaces.
> 
> Why doesn't it count? The user doesn't need to write that code, the translator does.

I remember a time when people here were joking about all the boilerplate you have to write when using java and that it's only usable with an IDE. Now we've got a C++ interfacing which requires lots of boilerplate and is only usable with an external translater tool...

I guess that would be acceptable if there is a real benefit, but I have not seen a single argument for the current behavior in this thread. It's great that we can workaround the scoping with lots of boilerplate, but when is C++ namespaces introducing a scope in D actually useful? Can you give an example where this scoping is necessary? So far I have not seen a single person happily using that scoping feature.

-- 
Johannes
August 02, 2018
Am Wed, 01 Aug 2018 16:04:01 -0700 schrieb Walter Bright:

>> Certainly, it does come across like you didn't trust the D module system to do its job for some reason.
> 
> Reorganizing the code into modules means potentially forcing users to split code from one C++ file into multiple D files. How's that really going to work if you have a translation tool? One of the aspects of Java I didn't care for was forcing each class into its own file.

Why would that not work with a translation tool? Just establish a fixed C+ + namespace / D module mapping, then whenever processing something in a C+ + namespace append the declaration to the corresponding file.

> 
> So while Manu is clearly happy with cutting up a C++ file into multiple
> D files,
> I doubt that is universal. His proposal would pretty much require that
> for anyone trying to work with C++ namespaces who ever has a name
> collision/hijack or wants to make the code robust against
> collision/hijacking.
> 
> An example of silent hijacking:
> 
>     extern (C++, "ab") void foo(long); // original code ... lots of code
>     ...
>     extern (C++, "cd") void foo(int); // added later by intern, should
>     have been
>                                       // placed in another module
>     ... a thousand lines later ...
>     foo(0); // OOPS! now calling cd.foo() rather than ab.foo(), D sux
> 
> You might say "nobody would ever write code like that." But that's like the C folks saying real C programmers won't write:
> 
>      int a[10];
>      for (int i = 0; i <= 10; ++i)
>         ...a[i]...
> 
> But we both know they do just often enough for it to be a disaster.
> 
> Now, with D:
> 
>      extern (C++, ab) void foo(long);
>      foo(0);    // works!
>      ---
>      extern (C++, ab) void foo(long);
>      extern (C++, ab) void foo(int);   // error!
>      ---
>      extern (C++, ab) void foo(long);
>      extern (C++, cd) void foo(int);
>      foo(0);    // error!
> 
> I juxtaposed the lines so it's obvious. It's not so obvious when there's a thousand lines of code between each of those lines. It's even worse when foo(long) sends a birthday card to your daughter, and foo(int) launches nuclear missiles.

If you insist on using a 'translator' tool anyway, it's trivial to detect
this problem automatically in such a tool.

-- 
Johannes
August 01, 2018
On 8/1/2018 12:01 PM, Manu wrote:
> You've never justified the design
> complexity and the baggage it carries.
Don't confuse you not agreeing with it with I never justified it.

And please don't confuse me not listening to you with me not agreeing with you.

It *is* possible for reasonable people to disagree, especially when any solution will involve many tradeoffs and compromises.
August 02, 2018
Am Wed, 01 Aug 2018 16:04:01 -0700 schrieb Walter Bright:

> 
> Now, with D:
> 
>      extern (C++, ab) void foo(long);
>      foo(0);    // works!
>      ---
>      extern (C++, ab) void foo(long);
>      extern (C++, ab) void foo(int);   // error!
>      ---
>      extern (C++, ab) void foo(long);
>      extern (C++, cd) void foo(int);
>      foo(0);    // error!
> 
> I juxtaposed the lines so it's obvious. It's not so obvious when there's a thousand lines of code between each of those lines. It's even worse when foo(long) sends a birthday card to your daughter, and foo(int) launches nuclear missiles.

You probably didn't completely think this through: Earlier you suggested to use aliases to avoid explicitly specifying the c++ scopes. Then you suggested to use mixins or translator tools to automate alias generation and avoiding manually writing that boiler plate code. But if you do that:

-------------------------
extern (C++, ab) void foo(long);
extern (C++, cd) void foo(int);
alias foo = ab.foo;
alias foo = cd.foo;
-------------------------

You've now got exactly the same problem with hijacking...

So the benefit of explicit c++ namespace scoping is only a benefit if you do not use this alias trick. But then you face all other problems mentioned earlier...

As a result, everybody now has to use the aliasing trick, the hijacking problem still exists and we have to write lots of useless boilerplate.

-- 
Johannes
August 01, 2018
On Wed, 1 Aug 2018 at 22:15, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On 8/1/2018 12:01 PM, Manu wrote:
> > You've never justified the design
> > complexity and the baggage it carries.
> Don't confuse you not agreeing with it with I never justified it.
>
> And please don't confuse me not listening to you with me not agreeing with you.
>
> It *is* possible for reasonable people to disagree, especially when any solution will involve many tradeoffs and compromises.

We have demonstrated consistent ongoing issues and frustration for 6
years. Your counter-argument is hypothetical at best, and has never
demonstrated an advantage.
Can you agree on that? I don't think that's a subjective quantity
where reasonable people may disagree.

If the namespace is useful in a minor subset of cases in the way you
argue, then it should be a secondary feature which can be deployed
independently as appropriate.
It should not be conflated into a basic mangling request which we
can't opt-out of. We are yet to observe a case where it was useful,
and we have to do ongoing work to try and un-do the effect on our
code.

I also want to stress, I'm not trying to change the existing code. I'm
not for a breaking change.
I think implementing the string alternative is the only robust way
forward, because that also solves the additional problem of being able
to name C++ namespaces that are invalid D keywords, which has bitten
me in at least 2 particularly noteworthy occasions.
Your hypothetical scenario may continue to be served if you like.
August 02, 2018
Am Wed, 01 Aug 2018 22:13:05 -0700 schrieb Walter Bright:

> On 8/1/2018 12:01 PM, Manu wrote:
>> You've never justified the design complexity and the baggage it carries.
> Don't confuse you not agreeing with it with I never justified it.
> 
> And please don't confuse me not listening to you with me not agreeing with you.
> 
> It *is* possible for reasonable people to disagree, especially when any solution will involve many tradeoffs and compromises.

In your most recent posts you provided some rationale for this, but nowhere as much as would have been necessary if anybody else proposed this feature and had to write a DIP for it. Introducing c++ namespace scopes added quite some complexity to the language and so far, you seem to be the only proponent of this, whereas we have many opponents. In the DIP process, such a change would have required quite a solid justification, examples, comparison to alternative solutions etc. Such a detailed rationale has never been given for this feature.

-- 
Johannes
August 02, 2018
On 8/1/2018 10:06 PM, Johannes Pfau wrote:
> I guess that would be acceptable if there is a real benefit, but I have
> not seen a single argument for the current behavior in this thread.

Please read my postings in this thread, then.
August 02, 2018
On 8/1/2018 11:08 PM, Manu wrote:
> I think implementing the string alternative is the only robust way
> forward, because that also solves the additional problem of being able
> to name C++ namespaces that are invalid D keywords, which has bitten
> me in at least 2 particularly noteworthy occasions.

Which keywords were those?

In any case, this is a general problem when dealing with C and C++ interoperability, and your solution would only deal with one case of it. For example,

 --- C++ ---
 void with();
 int scope;
 enum pure;
 -----------

If this problem were to be solved, it should be solved, not hacked for one case only. There are many ways of dealing with it:

1. pragma(mangle)

2. change the names in the C/C++ side

3. use a macro -Dwith=with_ when compiling the C/C++ code

4. write wrappers/forwarders/trampolines in C/C++, compile them and link them in

5. write a tool that patches the object file (not as hard as it sounds, the symbol table is usually in one spot, but of course the patcher would have to be implemented for each object file format). I've written object file patchers before, they work surprisingly well. Nobody else does it, presumably because the thought inspires terror :-)

6. provide some switch to the D compiler to rename A=>B in the object file symbols, though I'd worry such would slow the compiler down

7. perhaps amend the language such that an identifier of the form "__keyword" would appear in the object file as "keyword".
August 02, 2018
On 8/1/2018 11:08 PM, Manu wrote:
> We have demonstrated consistent ongoing issues and frustration for 6
> years.

Have you ever tried the alias method I proposed?