July 30, 2018
On 7/30/2018 1:05 PM, Walter Bright wrote:
> I'll look into this.

Check this:
---
  extern (C++, ns) { int foo(); }

  mixin template X() {  extern (C++, ns) int bar(); }
  mixin X!() x;
  alias bar = x.ns.bar;

  void main() {
    foo();
    bar();

    pragma(msg, foo.mangleof);
    pragma(msg, bar.mangleof);
  }
---

  dmd -c test
  ?foo@ns@@YAHXZ
  ?bar@ns@@YAHXZ
July 30, 2018
On 7/30/2018 5:07 AM, Daniel N wrote:
> I tried that but it mangles wrong.. it includes "S1" which is not what you want,

You're right, and I fixed that in a reply to Atila.
July 30, 2018
On 7/30/2018 9:45 AM, Manu wrote:
> Sure it 'works', but it's an annoying point of friction, and it
> doesn't need to be that way.

You can reduce it to:

    mixin(cppNamespace("ns", "void foo();"));


>> You haven't explained why you can't just move the namespace ns declarations in
>> one file together.
> 
> Are you serious?

Yes, please explain why you can't coalesce the namespace declarations in one C++ file into one namespace declaration.


> When torrents of people complain, you can send every single one of
> them to me, tell me "I told you so", and I'll eat my hat.

Apologies don't pay the bills. C++ is full of such stuff, and the bill for it is staggering.

July 30, 2018
On 7/30/2018 6:48 AM, Atila Neves wrote:
> This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is.

You're right.
July 30, 2018
On Mon, 30 Jul 2018 at 13:25, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On 7/30/2018 9:45 AM, Manu wrote:
> > Sure it 'works', but it's an annoying point of friction, and it doesn't need to be that way.
>
> You can reduce it to:
>
>      mixin(cppNamespace("ns", "void foo();"));
>
>
> >> You haven't explained why you can't just move the namespace ns declarations in one file together.
> >
> > Are you serious?
>
> Yes, please explain why you can't coalesce the namespace declarations in one C++ file into one namespace declaration.

We're talking about multiple C++ files, not one.
Problems arise when you import 2 modules since the namespaces collide.
You need to disambiguate with the D module identifier anyway, which
self-defeats the whole design! The C++ namespaces are redundant.
They just lead to user confusion, and more tedious metacrobatics when
scanning for things. No scanning meta supports recursing into C++
namespaces.

> > When torrents of people complain, you can send every single one of them to me, tell me "I told you so", and I'll eat my hat.
>
> Apologies don't pay the bills. C++ is full of such stuff, and the bill for it is staggering.

I'm suggesting there will not be any such bug report. The result will be simpler and more intuitive, and there will be less complaints, not more.

We don't want C++'s namespaces in D. I have no idea why you do... cus
you go on and on about how complex and horrible they are. And now we
have a thing that's not like C++ namespaces, and also not like normal
D code (where normal D modules would be absolutely fine).
I agree with you completely... I don't want C++ namespaces in D. I
also don't want _anything like them_. We're all happy with the D
module system, that's how we want to organise our code. Please let us
organise our code using the D module system.
July 30, 2018
On 29.07.2018 09:37, Walter Bright wrote:
> On 7/28/2018 11:06 PM, Nicholas Wilson wrote:
>> Then again I don't see any (non philosophical/compiler front end internal) issue why you can't reopen a namespace. D is supposed to be pragmatic, after all.
> 
> Consider if a template reopens a namespace and throws a few more overloads in it. Then, what's in the namespace is dependent on which expansions are done, in which order.

How would that work? I don't think this is possible.

> Throw in the inevitable circular references. Do people write code like that? Sure as shootin', they do, and they demand that it work, and file lots of bug reports about the erratic behavior.
> ...

Well, they already can do this with the global scope.

> Next, consider a function body throwing a few more overloads in. Now, if the function body is compiled or not (and the compiler tries to avoid compiling bodies unless it has to) affects code that is outside of the function.
> ...

Again, this does not seem possible.

> C++ is full of stuff like that. The difference is, when code fails in some bizarre way, programmers blame themselves and throw money at Scott Meyers to educate them on how to avoid writing such code. For D, they blame me.
> 
> The last time we fixed scope lookup to make it more complicated was with imports, and that took YEARS to sort out.
> 
> So I'm a little reluctant to add features that will result in a rat's nest of problems I can neither explain nor fix, then someone will add 4000 incomprehensible lines to fix 2 cases and add 5 or 6 bizarre regressions in the process and people complain the compiler is unstable. :-)

Well, for Atila, the only issue is that there cannot be two namespace declarations of the same name in the same source file. I don't think it is necessary to change scope lookup rules at all, just put declarations from namespaces with identical names into the same name space.

Note that we already need to define semantics for code like this:

struct ns{
static:
    int decl0;
    static if(is(typeof(reopenNS1))) mixin(reopenNS1);
}

int arbitrarily_many_intermediate_declarations0;

enum reopenNS1=q{
    int decl1;
    static if(is(typeof(reopenNS2))) mixin(reopenNS2);
};

int arbitrarily_many_intermediate_declarations1;

enum reopenNS2=q{
    int decl2;
    static if(is(typeof(reopenNS3))) mixin(reopenNS3);
};

static assert(is(typeof(ns.decl0+ns.decl1+ns.decl2)));

In terms of lookup, this is a similar problem to namespaces. I think Atila could probably even emit ugly code like this to solve his original problem, but it would slow down compilation unnecessarily. There are no new lookup issues here.

July 30, 2018
On 7/30/2018 2:12 PM, Manu wrote:
> We're all happy with the D
> module system, that's how we want to organise our code. Please let us
> organise our code using the D module system.

I have literally no idea what you mean. That's why I suggest you show what your C++ code looks like, and what you want to do with modules in D.

July 30, 2018
My issue is you're presenting solutions. But I have no idea what the problem is, because every time I present a solution to the examples you give, you say it's no good, because your problem is something else.

I cannot reverse engineer what the issue is from your proposed solution.

My second point is that changing the language is a last resort solution, not a first resort.

Thirdly, C and C++ are loaded to the gills with seemed-like-a-good-idea-at-the-time solutions that turned out to have bad unintended consequences that bork up the language for everyone down the line. D has some of those, too.

Forgive me, but:

   extern (C++, "ns")

has a definite smell about it of something going awry, and the idea that it shouldn't introduce a scope because nobody relies on C++ namespaces being in a scope despite that being the whole point of namespaces is a giant red flag of something terribly wrong somewhere.
July 31, 2018
On Mon, 30 Jul 2018 at 23:15, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> My issue is you're presenting solutions. But I have no idea what the problem is, because every time I present a solution to the examples you give, you say it's no good, because your problem is something else.

I'm not asking for workarounds or 'solutions'. I know the workarounds
very well, because I've been writing them repeatedly for years. I want
to see this mistake corrected.
It's not a case of "can't do the thing", this is a case of "i hate
doing the thing (ie, workarounds), the results are particularly
unsatisfying, and the whole basis for the problem is unfounded".

We repeat it over and over.
The case on trial today is that it can't be 'reopened', which is
awkward in cases of generative programming (like Atila's case), and is
a conversation that shouldn't even need to exist; a namespace given
for mangling doesn't exhibit this issue.
We can't specify some valid C++ namespace names that are D keywords.
(also, 'std' is particularly annoying, since it conflicts with phobos)
Other cases where it conflicts with itself when you import 2 modules
with symbols spanning the same namespace, which is more common than
not. The resolution is explicit disambiguation using the D module
scope (which is the whole point of D modules), and so the C++
namespace scope is just redundant.

Given your favourite example:
----
module a;
extern(C++, ns) void foo();
----
module b;
extern(C++, ns) void foo();
-----
module c;
import a, b;
foo(); // error: ambiguous
ns.foo(); // error, ambiguous (obviously)
a.ns.foo(); // naturally, this works... it's the D module that
correctly organises the symbol. 'ns' is worthless here

Just like every other instance in D code ever where modules are used
to organise symbols.
I don't have to convince you that D modules work well... you need to
convince us that D modules are insufficient.

ns is just annoying complexity, and it interferes with other code.
Atila's thing about 'reopening' namespaces is a non-issue if namespace
was just for mangling. The whole class of problem ceases to exist. (I
have been frustrated by this same problem too)
Scanning meta doesn't have to learn to identify and recurse into C++
namespaces to traverse that edge case where a module has some C++
symbols. No scanning meta every written is equipped with that logic.
There's no advantage to the ns scope, and it only brings challenges.
None of any of our time ever needed to be wasted here. The feature as
designed absolutely has not solved any form of problem. It has not
saved more time than it's wasted, and it never will.

Not to mention that it's ugly and leads to undesirable and unintuitive
symbol names.
When a C++ namespace spans modules (ie, the C++ namespace encloses the
whole library's api), translation to D looks like this:

module ns.submodule;
extern(C++, ns) void foo();

The name is:
ns.submodule.ns.foo(); // <- ns is already present at the head of the
qualified name, there's no point repeating it.


The converse case where modules are divided by their namespace (which
naturally maps to D modules):

module cpplib.ns;
extern(C++, ns) void foo();

Now the name is:
cpplib.ns.ns.foo(); // <- why would anyone want that?


In both cases it's just a repeat of what's already in the module name.
But the redundancy is more than a nuisance in certain forms of scanning meta.

And got forbid the case where C++ namespaces are embedded (namespace for lib name, another for the module), and we have this:

module lib_ns.module_ns;
extrern(C++, lib_ns) extern(C++, module_ns) void foo();

The name is:
lib_ns.module_ns.lib_ns.module_ns.foo(); // <- ....words can't even


> My second point is that changing the language is a last resort solution, not a first resort.

This isn't a last-resort, this was truly a first-resort... I started
making this noise within some number of hours after the appearance of
the design countable on my fingers. (far less aggressively, having not
spent years of my life stewing on this)
You've just blocked the conversation for sufficiently long that now
you're able to say that sentence you just said. Was that a deliberate
strategy? I feel like that strategy's been used before.

That said, I'm not proposing a language 'change', we can just support a string version in parallel and everything's fine if we don't want to deprecate the scope version.


> Thirdly, C and C++ are loaded to the gills with seemed-like-a-good-idea-at-the-time solutions that turned out to have bad unintended consequences that bork up the language for everyone down the line. D has some of those, too.

extern(C++, ns) is the poster child of exactly that.
In this case, it seemed-like-a-good-idea to one person and was
implemented with no consultation of anyone. The design was never
presented or scrutinised. It just merged, and when we promptly
complained, our criticism were rejected on principle.
Maybe we should write up a retro-DIP, and see if it passes review...?


> Forgive me, but:
>
>     extern (C++, "ns")

It should be a string such that valid C++ namespace names that are grammatically invalid in the extern expression aren't arbitrarily rejected.


> has a definite smell about it of something going awry, and the idea that it shouldn't introduce a scope because nobody relies on C++ namespaces being in a scope despite that being the whole point of namespaces is a giant red flag of something terribly wrong somewhere.

C++ programmers depend on namespaces to scope stuff _in C++_.
D programmers depend on modules to scope stuff (and it's a much better
solution).
Why don't you have faith in using modules to scope stuff? It's been
working well for us all this time. People don't often complain that
they have trouble scoping things intelligently in D.

You need to argue a reason for the complexity, it's not my job to
argue against the complexity that shouldn't ever have existed.
Justifying the complexity is your burden of proof; it was never
discussed or proven out.
I can't argue my case any more than I have, but you haven't argued
yours at all other than a feeling that is 'smells', and a sense of red
flag that the D module system, which works perfectly fine in general,
has some inexplicable weakness in this one case for some reason that's
never been identified.

You fear an unjustified torrent of bug reports if we were to fix this, but you don't acknowledge the constant stream of bug reports with the design as-is. You've got this backwards.
July 31, 2018
On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote:
> On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote:
>> On 7/28/2018 11:18 AM, Manu wrote:
>>> Make a PR that implements namespace as a string... I will use that fork of D forever.
>>
>> 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.)
>>
>> 2. Use:
>>
>>    pragma(mangle, "the mangled name")
>
> This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is.

What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now.

template fun()
{
    pragma(mangle, "_ZN2ns3funEv")
    extern(C++)
    void fun() {}
}

mixin fun;