September 05, 2018
On 05/09/2018 9:35 PM, Jonathan M Davis wrote:
> On Wednesday, September 5, 2018 2:30:25 AM MDT Walter Bright via
> Digitalmars-d wrote:
>> On 9/4/2018 10:16 PM, Manu wrote:
>>> I'm serious, you can have your cake, and potentially, I could have my
>>> cake too, and everybody would be happy... nobody would be sad.
>>
>> If it is the same, I provided solutions in those threads. The incomplete
>> example code did not make use of them.
>>
>> I don't know why you have "no option" left.
> 
> If I understand correctly, what it basically comes down to is that Manu
> finds all of the workarounds that you've suggested to be so annoying as to
> be intolerable. And after running into some of the same problems yet again,
> he felt the need to complain about it again and beg you to change your mind,
> since he feels that he has no idea how to convince you. I get the impression
> that he thinks that his proposed solution is so obviously better that he
> doesn't understand why you don't see that it's better, but I don't know.
> Either way, I think that we all know that it can be very difficult to
> convince you of something (though that's true of many of us around here). :)
> 
>>From what I understand of the situation, I'm inclined to agree with Manu's
> position on this topic, but I thought that it was clear from the previous
> discussion that if there were any chance of anything changing, we were going
> to need a DIP. Based on everything that's been said thus far, I question
> that that stands much chance of convincing you, but I do think that we need
> a clear definition of the proposed solution so that we can avoid talking
> passed each other, which seemed to be happening at least some of the time in
> the recent thread. Either way, unless someone can come up with an example of
> the problem or argument about it that somehow convinces you when the
> previous examples and arguments didn't, I'm not sure that there's much point
> in arguing about it without at least having a clear DIP on the topic.
> 
> - Jonathan M Davis

+1 My interpretation is very similar, only difference is that Manu is asking for is removal of some artificial restrictions put in place to prevent possible problems that probably won't appear in D. I agree with the solution you have provided to move forward. I think we're done arguing, Walter just doesn't seem to want to accept Manu's use case as-is.
September 05, 2018
On Wednesday, 5 September 2018 at 08:30:25 UTC, Walter Bright wrote:
> On 9/4/2018 10:16 PM, Manu wrote:
>> I'm serious, you can have your cake, and potentially, I could have my
>> cake too, and everybody would be happy... nobody would be sad.
>
> If it is the same,

It is

> I provided solutions in those threads. The incomplete example code did not make use of them.

Those "solutions" do not satisfactorily solve the problem, hence:

>I have to contort my code to undo a thing that should never have been there. It's truly >embarrassing. I can't show this to people.
>
>***I can not present my work to stakeholders with a straight face***

I don't think I could either.

> I don't know why you have "no option" left.

There is one: add it to LDC, which will accept it, see https://github.com/ldc-developers/ldc/issues/2800#issuecomment-410817126 but this is a language feature we (LDC) would rather not have an upstream diff for.

This is a prime example of an industry blocker if ever there was. Yes there has been a lot of talking past each other, but surely you understand _what_  Manu is wanting even if you seem to think that your workarounds (which you called solutions) are sufficient. It is backwards compatible and solves a clear need, I don't see why this is such a contentious issue.


September 05, 2018
On Wednesday, September 5, 2018 7:03:26 AM MDT Nicholas Wilson via Digitalmars-d wrote:
> This is a prime example of an industry blocker if ever there was. Yes there has been a lot of talking past each other, but surely you understand _what_  Manu is wanting even if you seem to think that your workarounds (which you called solutions) are sufficient. It is backwards compatible and solves a clear need, I don't see why this is such a contentious issue.

Based on everything Walter said in the previous thread, it honestly seems to me to be primarily like he just can't give up on the idea that D has to worry about modeling C++ namespaces. Pretty much all of the extra complications that come from the current approach stem from insisting on modeling namespaces in D instead of just treating the namespace as part of the information that you give to the compiler to indicate what the symbol in D is supposed to correspond to in C++ when the compiler goes to mangle it.

What Walter did makes perfect sense if you assume that D needs to care about namespaces when using the C++ symbol in D, but the conclusion of the rest of us when looking at the problem has been that D really doesn't need to care about the namespaces beyond mangling, because D modules already solve the problem. In actuality, there's no more need to worry about a C++ symbol's namespace when using it in D than there is to have to care about which header file a C symbol lives in when you use it in D. The module you put it in will likely relate to the header file that it comes from, and in the case of a C++ symbol, it may even relate to the namespace that it's in in C++, but that's just a matter of sanely organizing your bindings in D so that folks using the code will have an easy time finding the symbols if they know where they live in C/C++. It's not required for actually differentiating the symbols when using them in D. The modules already take care of that quite well.

And if you really have a situation where multiple namespaces with the same symbol name live in a C++ header, and you want to put them in the same module in D, it should be trivial to stick them in structs, classes, or templates to namespace them like folks already sometimes do with D code when they want to emulate namespaces in D. Or if we left the current implementation in addition to what Manu wants, then the current approach could be used in those cases. So, the primary situation that Walter brought up with using the module system to differentiate symbols rather than having the compiler emulate the namespace like it currently does should be very solvable with what Manu wants, whereas every issue that Manu and Atila brought up required jumping through hoops in order to get it working with the current solution, and it frequently ends up not only being much harder to implement, but it's less user-friendly for the programmers using the bindings.

So, if you can accept the idea that there really is no need to emulate C++ namespaces in D - even if you want to be able to stick multiple namespaces in the same module - then I really don't see any reason to prefer the current approach to extern(C++, "namespace") like Manu wants. But for whatever reason, Walter just doesn't seem to accept the idea that it's unnecessary to emulate namespaces in D in order to link to them, and he thinks that all of the hoops that it causes you to jump through are worse than the extra hoops that you would have to jump through to get multiple namespaces in the same file if extern(C++, namespace) weren't a thing. I can understand that from the standpoint that extern(C++, namespace) has already been implemented, whereas extern(C++, "namespace") has not been. So, even if we were to then have both instead of replacing one with the other, there's definitely work involved. However, I fail to understand why extern(C++, namespace) is superior from a technical perspective. Rather, it clearly has some serious drawbacks in comparison to extern(C++, "namespace"). But be it because of the effort involved with implementing a new solution, or because the current solution was his idea, or because of some other reason, thus far, Walter just doesn't seem to want to come around to the idea that all we need is the mangling, and then we should be able to do everything else we need with what D already provides. Worst case, we might need to make adjustments to make sure that something like

static Namespace
{
    extern(C++, "Namespace") static bool freeFunc(int foo);
}

can compile without expecting freeFunc to be part of a struct. But I'm pretty sure that even if that wouldn't work, a template could be used as the namespace isnead, and we could even choose to leave in

extern(C++, Namespace) bool freeFunc(int foo);

for the rare case where that makes more sense than simply letting the module system do its job.

But regardless, I'm with you and Manu at this point in that I don't understand why extern(C++, "Namespace") isn't a clearly better (and simpler) solution overall. But maybe we'll get lucky and after Walter has thought about it long enough, he'll come around. Either way, per the current process, we would clearly need a DIP even if Walter already agreed. So, the next step is to write a DIP, and hopefully it can be written well enough that it's appropriately convincing unlike everything that has been argued thus far.

- Jonathan M Davis



September 06, 2018
On Wednesday, 5 September 2018 at 13:53:15 UTC, Jonathan M Davis wrote:

Very well said, thanks.

> Based on everything Walter said in the previous thread, it honestly seems to me to be primarily like he just can't give up on the idea that D has to worry about modeling C++ namespaces.

That is the conclusion I came to as well.

> What Walter did makes perfect sense if you assume that D needs to care about namespaces when using the C++ symbol in D, but the conclusion of the rest of us when looking at the problem has been that D really doesn't need to care about the namespaces beyond mangling, because D modules already solve the problem.

I think this is the key insight, everything else follows from this.

> But regardless, I'm with you and Manu at this point in that I don't understand why extern(C++, "Namespace") isn't a clearly better (and simpler) solution overall. But maybe we'll get lucky and after Walter has thought about it long enough, he'll come around. Either way, per the current process, we would clearly need a DIP even if Walter already agreed. So, the next step is to write a DIP, and hopefully it can be written well enough that it's appropriately convincing unlike everything that has been argued thus far.

Indeed, It is a pity the DIP pipeline is so full.

Manu, what timeline do you ideally need this by? and do you have an implementation? Putting it into LDC is probably going to be the fastest given there are 3 high impact DIPs in the queue already + however long takes to get this trough and then implemented.

September 10, 2018
On Wednesday, 5 September 2018 at 13:53:15 UTC, Jonathan M Davis wrote:
> On Wednesday, September 5, 2018 7:03:26 AM MDT Nicholas Wilson via Digitalmars-d wrote:
>> [...]
>
> Based on everything Walter said in the previous thread, it honestly seems to me to be primarily like he just can't give up on the idea that D has to worry about modeling C++ namespaces. Pretty much all of the extra complications that come from the current approach stem from insisting on modeling namespaces in D instead of just treating the namespace as part of the information that you give to the compiler to indicate what the symbol in D is supposed to correspond to in C++ when the compiler goes to mangle it.
>
> [...]

I wholeheartedly agree. C++ namespaces are a C++ language idea that D has discarded in favor of much simpler facilities. Injecting that <expletive-deleted> back into D when linking to C++ is polluting D with needless complexity at odds with that gain in simplicity. The name collision problem with two namespaces containing the same name can be resolved with much simpler facilities. For example, at the point of the extern declaration, the name of the linked entity could be provided as an optional third parameter so that the name in D could be different. I'm sure many other simple schemes could be invented, more consistent with D's approach.

September 10, 2018
On Mon, 10 Sep 2018 at 13:40, Carl Sturtivant via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Wednesday, 5 September 2018 at 13:53:15 UTC, Jonathan M Davis wrote:
> > On Wednesday, September 5, 2018 7:03:26 AM MDT Nicholas Wilson via Digitalmars-d wrote:
> >> [...]
> >
> > Based on everything Walter said in the previous thread, it honestly seems to me to be primarily like he just can't give up on the idea that D has to worry about modeling C++ namespaces. Pretty much all of the extra complications that come from the current approach stem from insisting on modeling namespaces in D instead of just treating the namespace as part of the information that you give to the compiler to indicate what the symbol in D is supposed to correspond to in C++ when the compiler goes to mangle it.
> >
> > [...]
>
> I wholeheartedly agree. C++ namespaces are a C++ language idea that D has discarded in favor of much simpler facilities. Injecting that <expletive-deleted> back into D when linking to C++ is polluting D with needless complexity at odds with that gain in simplicity. The name collision problem with two namespaces containing the same name can be resolved with much simpler facilities. For example, at the point of the extern declaration, the name of the linked entity could be provided as an optional third parameter so that the name in D could be different. I'm sure many other simple schemes could be invented, more consistent with D's approach.

This is a problem that doesn't need a solution. Just use modules; this
is precisely what they're for.
I, for one, have faith in the module design.
September 12, 2018
So my understanding is that the main issue with extern(C++,"ns") is
functions that have different C++ name-spaces overriding each other in
unexpected ways.
How feasible is to simply disallow functions/variables/objects/... with the
same name but a different "ns" being in the same module?


September 12, 2018
On Wednesday, 12 September 2018 at 03:59:30 UTC, Danni Coy wrote:
> So my understanding is that the main issue with extern(C++,"ns") is
> functions that have different C++ name-spaces overriding each other in
> unexpected ways.
> How feasible is to simply disallow functions/variables/objects/... with the
> same name but a different "ns" being in the same module?

Very. The compiler would do it automatically because they would cause name collisions.
September 11, 2018
On Tuesday, September 11, 2018 9:59:30 PM MDT Danni Coy via Digitalmars-d wrote:
> So my understanding is that the main issue with extern(C++,"ns") is
> functions that have different C++ name-spaces overriding each other in
> unexpected ways.
> How feasible is to simply disallow functions/variables/objects/... with
> the same name but a different "ns" being in the same module?

If we had extern(C++, "NS"), then all it would affect would be mangling and all of the normal rules for conflicting symbols would be in force. So, if you tried to put two symbols with the same name but from different namespaces in the same module, you'd get an error just like if they were D functions that conflicted. Disallowing it wouldn't be the problem. The problem would be if you were trying to match the C++ header file and thus have the two namespaces in the same file without a conflict, and that wouldn't work unless you could do something like put the symbol inside a struct or template to effectively namespace it - or if the current extern(C++, NS) mechanism were left in place in addition to adding extern(C++, "NS").

But for the most part, this is a non-issue, because the sane thing to do would be to just put different namespaces in different modules even if they were in the same header file in C++ - maybe pkg.headerfile.namespace instead of pkg.headerfile like you might do if everything in the header file were in the same namespace. It might be more of a problem with something that generated the bindings automatically, but mostly, the issue seems to be that Walter wants to be able to completely follow the C++ header scheme when you create the bindings, whereas most of the rest of us don't really care about being that exact about it if the header file did something like have multiple namespaces with symbols that would conflict if they were in the same namespace. Since the current scheme effectively creates namespaces inside of the module instead of just affecting the name mangling, you can stick as many namespaces in the module as you want without worrying about conflicts, but you then get other fun problems like having to declare everything in the namespace sequentially and having to refer everything in the namespace with the namespace unless you alias it all.

So really, the most flexible solution would probably to have
extern(C++, "NS") which only affects the mangling and then make sure that it
works to do something like

struct Namespace
{
    extern(C++, "Namespace") static void foo(int bar);
}

thereby allowing you to have symbols from multiple namespaces in the same module even if they have conflicting names. In most cases, people would then just do

extern(C++, "Namespace") void foo(int bar);

and it's nice and simple, whereas if they really wanted to put conflicting symbols in the same module instead of just putting them in separate module like you would with D symbols, they could then explicitly namespace them. But given what we already have in the language, the simplest alternative would be to just add

extern(C++, "Namespace")

and leave

extern(C++, Namespace)

so that most code could use extern(C++, "Namespace"), and those rare cases where you really don't want to put conflicting symbols in separate modules, you use the current scheme of extern(C++, Namespace). The main downside is that having both constructs risks being confusing. Really though, there isn't much of a downside to the extern(C++, "Namespace") solution even if it were the only one.

- Jonathan M Davis



September 12, 2018
On Tue, 11 Sep 2018 at 20:59, Danni Coy via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>
>
> So my understanding is that the main issue with extern(C++,"ns") is functions that have different C++ name-spaces overriding each other in unexpected ways.
> How feasible is to simply disallow functions/variables/objects/... with the same name but a different "ns" being in the same module?

That's natural behaviour. You can't declare the same symbol twice in the same scope.