November 29, 2015
On 29 Nov 2015 11:30 am, "Jacob Carlborg via Digitalmars-d" < digitalmars-d@puremagic.com> wrote:
>
> On 2015-11-29 11:19, Iain Buclaw via Digitalmars-d wrote:
>
>> I keep telling them to fix that.  My suggestion of replacing them with meaningful errors was rejected.
>
>
> "rejected", what!! Any assertion in the compiler is a bug. Or was that
not from the compiler?
>

Someone put in those ICE's on the promise that at some point it would be detected in semantic pass before the symbol mangling was requested.  That promise was never kept.

For reference (or if you enjoy time travelling) https://github.com/D-Programming-Language/dmd/pull/4661


November 29, 2015
On 29 November 2015 at 20:40, Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 29 Nov 2015 11:30 am, "Jacob Carlborg via Digitalmars-d" <digitalmars-d@puremagic.com> wrote:
>>
>> On 2015-11-29 11:19, Iain Buclaw via Digitalmars-d wrote:
>>
>>> I keep telling them to fix that.  My suggestion of replacing them with meaningful errors was rejected.
>>
>>
>> "rejected", what!! Any assertion in the compiler is a bug. Or was that not from the compiler?
>>
>
> Someone put in those ICE's on the promise that at some point it would be detected in semantic pass before the symbol mangling was requested.  That promise was never kept.
>
> For reference (or if you enjoy time travelling) https://github.com/D-Programming-Language/dmd/pull/4661

Well they took a few hours of my life, and increased my anger level a couple of notches.
November 29, 2015
On 29 November 2015 at 20:17, Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 29 Nov 2015 6:17 am, "Manu via Digitalmars-d" <digitalmars-d@puremagic.com> wrote:
>>
>> On 29 November 2015 at 14:57, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> >
>> > D does not support C++ semantics. You cannot split namespaces into
>> > multiple
>> > files in D, nor can you add symbols to an existing namespace. For
>> > namespace
>> > NS, all the declarations in NS have to be in one file and between the {
>> > },
>> > just like any other scope in D.
>>
>> Then the feature fails. You can't put the entire STL in one file.
>> C++ doesn't namespace per file, it generally namespaces per project...
>> so this is the common case; every module define symbols in the same
>> C++ namespace.
>>
>>
>
> This (and response below about mangling) answers a recent question in a PR I made.  I had noticed the same when writing a testsuite case, only to discover you can only declare `extern(C++, std)` once.  For me, having all related code for a test close together is a nice-to-have though.

It's a serious problem. I haven't been able to find any reasonable
solution. I've tried a bunch of stuff.
I think the cleanest solutions would be to either fix this, or to
allow public aliasing of private namespaces, that way the namespace is
kept in it's box and never pollutes the user's module scope on import.


>> >> Additionally to that, I don't really want the C++ namespaces to be visible to D; they should be for mangling purposes only.
>> >
>> >
>> > We considered making them for mangling only, and rejected it as
>> > unworkable,
>> > because then two identical names in different namespaces could not be
>> > distinguished by the D symbol table system.
>>
>> I understand, and that's fine, but it's not particularly useful unless I can make the namespace invisible and alias the namespaced symbols into D's module (user-accessible) scope. Otherwise importing 2 modules leads to conflicting namespace and symbol resolution is all messed up.
>>
>
> Renamed imports should work here?

How? I tried this every way I could think;

import x.y.NS : Thing; // expects that NS is a file...
import x.y : Thing = NS.Thing; // doesn't like 'NS.' in this statement
import x.y : this = NS; // ...or something. yeah, I was getting hopeful

I could only make this work with a proxy module, which doubles my module count:

internal/thing.d:
  module x.y.internal.thing;
  extern(C++, NS) struct Thing {}

thing.d:
  module x.y.thing;
  import x.y.internal.thing; // pollutes the local namespace with NS,
but since it's not public it doesn't cascade outwards
  alias Thing = NS.Thing; // aliases to a public module-level symbol

user.d:
  import x.y.thing;
  Thing t; // hooray, it works!


>> >> So I try code like this:
>> >>    private extern(C++, NS) struct Thing {}
>> >>    alias Thing = NS.Thing;
>> >>
>> >> The idea being that NS will not be available externally, and they
>> >> should use Thing in module scope instead, but that doesnt work with
>> >> errors:
>> >>    Error: module blah class blah.NS.Thing is private
>> >>
>> >> It seems aliasing a private thing into the public namespace does not make it accessible via that alias?
>> >
>> >
>> > Aliases do not change access permissions. They are just aliases.
>>
>> Maybe a special case for C++ namespaces? Or some other solution that
>> produces the same result.
>> It's a weird sort of permission this one, it's not that the symbols
>> are 'private'; I intend the user to use them, I just want the C++
>> hierarchy excluded from the symbol table and only accessibly by
>> controlled/explicit alias.
>>
>
> You may have already noticed, but `extern(C++, NS)` behaves more like importing a module, but rather than the module being in a separate file, it's contents are put inplace of the braces.

Yup, but `import` doesn't seem to have tools to deal with this case.

> Like importing modules in D, the namespace name itself is not a strong encapsulation (unlike e.g D enums), so whether you use Thing or NS.Thing, both will resolve to the same symbol.  The same should also be true when importing a namespace from another module.

It all goes south when you realise that every file in a C++ project
tends to be in the same namespace.
Import 2 of them, and then they start hiding eachother, and it all
goes south very quickly.

> I think your idea with aliases was just wishful thinking, aliases themselves never worked like that.

I thought aliases did produce a symbol in the scope they are declared?
Or do you mean with the private thing? Yeah...
Aliases are often used to sort out these sorts of scope/namespacing
issues, I've seen it come up lots of times.
November 29, 2015
On a related note, does D support inline namespaces? Apparently it affects mangling:

http://stackoverflow.com/questions/29764869/can-inline-namespaces-be-used-to-keep-backwards-compatibility-in-a-shared-librar

I use inline namespaces quite a bit and am curious of how D resolves those.


November 29, 2015
On Sunday, 29 November 2015 at 10:58:48 UTC, Manu wrote:
> On 29 November 2015 at 20:17, Iain Buclaw via Digitalmars-d
>> I think your idea with aliases was just wishful thinking, aliases themselves never worked like that.
>
> I thought aliases did produce a symbol in the scope they are declared?
> Or do you mean with the private thing? Yeah...
> Aliases are often used to sort out these sorts of scope/namespacing
> issues, I've seen it come up lots of times.

I remember when this feature was under discussion, I tried to argue against extern c++ creating a new scope, but alas no avail. So my current workaround looks something like this(but I didn't use it on a large scale yet):

private static struct Hidden
{
public:
    extern(C++, std) int fun();
}

// autogenerate all aliases with 'static foreach'?
alias fun = Hidden.std.fun;

if only static foreach would get accepted one day...

November 29, 2015
On 29 November 2015 at 21:22, Daniel N via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Sunday, 29 November 2015 at 10:58:48 UTC, Manu wrote:
>>
>> On 29 November 2015 at 20:17, Iain Buclaw via Digitalmars-d
>>>
>>> I think your idea with aliases was just wishful thinking, aliases themselves never worked like that.
>>
>>
>> I thought aliases did produce a symbol in the scope they are declared?
>> Or do you mean with the private thing? Yeah...
>> Aliases are often used to sort out these sorts of scope/namespacing
>> issues, I've seen it come up lots of times.
>
>
> I remember when this feature was under discussion, I tried to argue against extern c++ creating a new scope, but alas no avail. So my current workaround looks something like this(but I didn't use it on a large scale yet):
>
> private static struct Hidden
> {
> public:
>     extern(C++, std) int fun();
> }
>
> // autogenerate all aliases with 'static foreach'?
> alias fun = Hidden.std.fun;
>
> if only static foreach would get accepted one day...

Wow... I just didn't quite get there >_<
That's really horrible! But thanks! ;)
November 29, 2015
On 29 November 2015 at 19:56, Manu <turkeyman@gmail.com> wrote:
> ...

So I'm down to some link errors. I don't understand what's emitting
these (or not, it seems)... I've messed around a lot.
Is __ClassZ the typeinfo? Why would that be missing? Because it's
extern(C++)? I tried removing that and it made no difference :/

2> Error 42: Symbol Undefined _D15TypeInfo_Struct6__vtblZ
2>bin\Debug_x64\dplug.obj(dplug)
2> Error 42: Symbol Undefined _D14TypeInfo_Const6__vtblZ
2>bin\Debug_x64\dplug.obj(dplug)
2> Error 42: Symbol Undefined _D10TypeInfo_k6__initZ
2>bin\Debug_x64\dplug.obj(dplug)
2> Error 42: Symbol Undefined _D12TypeInfo_Aya6__initZ
2>bin\Debug_x64\dplug.obj(dplug)
2> Error 42: Symbol Undefined _D5libep9component9Component7__ClassZ
November 29, 2015
On Sunday, 29 November 2015 at 11:29:58 UTC, Manu wrote:
>
> Wow... I just didn't quite get there >_<
> That's really horrible! But thanks! ;)

Sorry, my memory was failing me, I dug up the real source now, it was a while ago and I hacked around a lot before I got it working, this is what I ended up with.

private extern(C++, std)
{
public:
  int fun();
}

// autogenerate all aliases with 'static foreach'?
alias fun = std.fun;

November 29, 2015
On Sunday, 29 November 2015 at 10:58:48 UTC, Manu wrote:
> On 29 November 2015 at 20:17, Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> I think your idea with aliases was just wishful thinking, aliases themselves never worked like that.
>
> I thought aliases did produce a symbol in the scope they are declared?
> Or do you mean with the private thing? Yeah...
> Aliases are often used to sort out these sorts of scope/namespacing
> issues, I've seen it come up lots of times.

Aliases usually seem to work a lot like copy-pasting. If you do something like

alias New = Orig;

then everywhere that New is used in the code, it's effectively replaced with Orig, and you never even see it in any error messages. It's pretty much just for the programmer's benefit - e.g. avoiding having to type out the entire import path for a symbol over and over:

alias foo = some.pkg.somewhere.foo;

But there's still really only one symbol that the compiler is dealing with. It's kind of like how the C/C++ compiler never really sees macros, though it's more controlled than that. For instance, try compiling this code on a 32-bit system:

long val;
size_t i = val;

You'll get an error message complaining about trying to convert a long to a uint, just like if the code looked like

long val;
uint i = val;

The only places that I can think of where aliases don't act quite like this are when they're not used to replace one symbol with another - e.g. with alias this or with using alias to bring a base class overload into the scope of a derived class.

- Jonathan M Davis
November 29, 2015
On Sunday, 29 November 2015 at 04:57:28 UTC, Walter Bright wrote:
> Aliases do not change access permissions. They are just aliases.

Note that this is a problem beyond Manu's use-case.  Example: subtyping via alias this currently requires the alias'd entity to be public, contra the example given on TDPL p.231 (see https://issues.dlang.org/show_bug.cgi?id=10996 for details).

This means that to use subtyping in practice requires internal implementation details to be revealed to the user, which isn't very nice :-(