(cast(Object)b).toHash()
D has this horrible notion that any interface can be for a COM object,
even though COM interfaces can only inherit from IUnknown (known
statically). Therefore, interfaces that don't inherit from IUnknown are
not considered Objects, even though they could and should be.
So you have to manually cast an interface to Object in order to call an
Object function.
-Steve

D has this horrible notion that any interface can be for a COM object, even
though COM
interfaces can only inherit from IUnknown (known statically). Therefore,
interfaces that
don't inherit from IUnknown are not considered Objects, even though they could
and should be.

Firstly, IUnknown is defined in the Phobos files, not a language built-in.
There might be
multiple IUnknowns, defined in different modules (e.g. because some set of
bindings has
its own copy). How should the compiler identify the IUnknown to use? By name?
By the
signatures of functions specified within it? By fully qualified name?
Secondly, I guess it's perfectly possible for some other system, besides COM,
to create
non-D objects that implement D interfaces.

So you have to manually cast an interface to Object in order to call an Object
function.

Which you can do, if you are certain that the object will always be a D object.
I guess
the whole point is to protect you from those cases where you can't be sure.
Stewart.

D has this horrible notion that any interface can be for a COM object,
even though COM
interfaces can only inherit from IUnknown (known statically).
Therefore, interfaces that
don't inherit from IUnknown are not considered Objects, even though
they could and should be.

Firstly, IUnknown is defined in the Phobos files, not a language
built-in. There might be multiple IUnknowns, defined in different
modules (e.g. because some set of bindings has its own copy). How
should the compiler identify the IUnknown to use? By name? By the
signatures of functions specified within it? By fully qualified name?

No, the compiler treats it specially, COM interfaces and classes have a
different layout than D objects, so the compiler has to generate different
code if the class implements an interface which inherits from
std.c.windows.com.IUnknown.
From the spec:
A COM interface is defined as one that derives from the interface
std.c.windows.com.IUnknown. A COM interface differs from a regular D
interface in that:
* It derives from the interface std.c.windows.com.IUnknown.
* It cannot be the argument of a DeleteExpression.
* References cannot be upcast to the enclosing class object, nor can they
be downcast to a derived interface. To accomplish this, an appropriate
QueryInterface() would have to be implemented for that interface in
standard COM fashion.
* Classes derived from COM interfaces are COM classes.
* The default linkage for member functions of COM classes is
extern(System).
* The first member of the vtbl[] is not the pointer to the InterfaceInfo,
but the first virtual function pointer.
----------------
There is nothing here that makes it seem like this is undetectable at
compile time.
IMO:
* cast(Object)someComInterface => compiler error
* Object o = someComInterface => compiler error
* Object o = someNormalInterface => success
Is all doable without incurring any problems.

Secondly, I guess it's perfectly possible for some other system, besides
COM, to create non-D objects that implement D interfaces.

But none of these exist today. All cases of 'alternative' interfaces have
alternative layouts and statically detectable triggers (such as IUnknown)
that would allow us to statically allow or disallow implicit casting to
Object. If we simply make a rule right now that alternative layouts have
to be typed with some modifier (like extern(C++) for example) we can have
implicit casting to object and get rid of all these ridiculous problems.

So you have to manually cast an interface to Object in order to call an
Object function.

Which you can do, if you are certain that the object will always be a D
object. I guess the whole point is to protect you from those cases
where you can't be sure.

The compiler can always be sure, it just isn't programmed to know it yet...
-Steve