Thread overview
why is `typeid` only half baked?
Nov 06, 2015
Or Dahan
Nov 06, 2015
Adam D. Ruppe
Nov 06, 2015
Jacob Carlborg
Nov 09, 2015
Or Dahan
Nov 09, 2015
Adam D. Ruppe
Jun 30, 2018
Mr.Bingo
November 06, 2015
When it comes to interfaces, apparently `typeid` always returns the type of the interface, An undocumented features, which is very misleading as for classes it returns the 'most derived type' (http://dlang.org/expression.html#TypeidExpression)

For example:

import std.stdio;

interface A {

}

class B : A {
    int y;
}

void foo(A a) {
    writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(a), a);
}

void main() {
    auto b = new B();
    writefln("Original scope got 'b' of typeid(%s) which is really '%s'", typeid(b), b);
    foo(b);
}

would print:

Original scope got 'b' of typeid(test.B) which is really 'test.B'
foo got 'a' of typeid(test.A) which is really 'test.B'

(notice that '%s' in the format correctly identifies 'a' to be of type 'B' in the same time that the typeid expression recognizes 'a' as of type 'A')

Rewriting foo as:

void foo(A a) {
    writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(cast(Object)a), a);
}

solves the issue (Thanks to David Nadlinger)

I must say I find this very counter-intuitive as its VERY LIKELY to have an interface as the polymorphic instance and sometimes you would want to query its exact type.

Obviously `typeid` can infer that 'a' is really an `Object` and then infer that its of type `B` (just as the writefln managed to).
This leads me the conclusion that `typeid` is only half-baked and can be improved to support interfaces in a more intuitive manner.

Any reasons why it inherently can't be improved to do so?

Thanks.
November 06, 2015
On Friday, 6 November 2015 at 16:38:04 UTC, Or Dahan wrote:
> Any reasons why it inherently can't be improved to do so?

You know, I was about to say no because interfaces can be objects from other languages... but the compiler is strict enough now that it can statically determine if that might be the case.

If the interface derives from IUnknown, it might be a COM object so it can't be sure it is a D class. Similarly if it derives from extern(C++). In those cases, the cast to Object returns null, and attempting to get typeid() off it is liable to outright crash.

But if it is a D interface... it should be ok doing an automatic cast to Object and trying to get typeinfo there.

The only problem it might have is if the typeinfo is in a dll. But I think that has been basically solved too.
November 06, 2015
On 2015-11-06 18:03, Adam D. Ruppe wrote:
> On Friday, 6 November 2015 at 16:38:04 UTC, Or Dahan wrote:
>> Any reasons why it inherently can't be improved to do so?
>
> You know, I was about to say no because interfaces can be objects from
> other languages... but the compiler is strict enough now that it can
> statically determine if that might be the case.
>
> If the interface derives from IUnknown, it might be a COM object so it
> can't be sure it is a D class. Similarly if it derives from extern(C++).
> In those cases, the cast to Object returns null, and attempting to get
> typeid() off it is liable to outright crash.
>
> But if it is a D interface... it should be ok doing an automatic cast to
> Object and trying to get typeinfo there.
>
> The only problem it might have is if the typeinfo is in a dll. But I
> think that has been basically solved too.

I had the same problem with "classinfo" [1], I guess that's basically the same as "typeid". The difference is that "classinfo" is specified in the spec that it will given information about the interface and not the class it might be an instance of [2].

[1] http://forum.dlang.org/post/mrl1uv$9ag$1@digitalmars.com
[2] http://dlang.org/property.html#classinfo

-- 
/Jacob Carlborg
November 09, 2015
On Friday, 6 November 2015 at 17:03:38 UTC, Adam D. Ruppe wrote:
> On Friday, 6 November 2015 at 16:38:04 UTC, Or Dahan wrote:
>> [...]
>
> You know, I was about to say no because interfaces can be objects from other languages... but the compiler is strict enough now that it can statically determine if that might be the case.
>
> If the interface derives from IUnknown, it might be a COM object so it can't be sure it is a D class. Similarly if it derives from extern(C++). In those cases, the cast to Object returns null, and attempting to get typeid() off it is liable to outright crash.
>
> But if it is a D interface... it should be ok doing an automatic cast to Object and trying to get typeinfo there.
>
> The only problem it might have is if the typeinfo is in a dll. But I think that has been basically solved too.

So, is it planned to be changed?
November 09, 2015
On Monday, 9 November 2015 at 10:22:09 UTC, Or Dahan wrote:
> So, is it planned to be changed?

I don't know, but I don't think so.
June 30, 2018
On Friday, 6 November 2015 at 16:38:04 UTC, Or Dahan wrote:
> When it comes to interfaces, apparently `typeid` always returns the type of the interface, An undocumented features, which is very misleading as for classes it returns the 'most derived type' (http://dlang.org/expression.html#TypeidExpression)
>
> For example:
>
> import std.stdio;
>
> interface A {
>
> }
>
> class B : A {
>     int y;
> }
>
> void foo(A a) {
>     writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(a), a);
> }
>
> void main() {
>     auto b = new B();
>     writefln("Original scope got 'b' of typeid(%s) which is really '%s'", typeid(b), b);
>     foo(b);
> }
>
> would print:
>
> Original scope got 'b' of typeid(test.B) which is really 'test.B'
> foo got 'a' of typeid(test.A) which is really 'test.B'
>
> (notice that '%s' in the format correctly identifies 'a' to be of type 'B' in the same time that the typeid expression recognizes 'a' as of type 'A')
>
> Rewriting foo as:
>
> void foo(A a) {
>     writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(cast(Object)a), a);
> }
>
> solves the issue (Thanks to David Nadlinger)
>
> I must say I find this very counter-intuitive as its VERY LIKELY to have an interface as the polymorphic instance and sometimes you would want to query its exact type.
>
> Obviously `typeid` can infer that 'a' is really an `Object` and then infer that its of type `B` (just as the writefln managed to).
> This leads me the conclusion that `typeid` is only half-baked and can be improved to support interfaces in a more intuitive manner.
>
> Any reasons why it inherently can't be improved to do so?
>
> Thanks.

Maybe this is because the compiler is computing the typeid at runtime? This is because a is of type A! It's clearly stated in the signature:


void foo(A a)
{
    writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(a), a);
}

typeid(a) looks at the type of a and see's A and hence that is what it is "locally"(it mistakenly evaluates typeid because it does not realize that a could be any B : A).

If typeid(cast(Object)a) produces a different result then clearly dmd is doing something wrong.





June 30, 2018
On 6/30/18 7:30 AM, Mr.Bingo wrote:
> On Friday, 6 November 2015 at 16:38:04 UTC, Or Dahan wrote:
>> When it comes to interfaces, apparently `typeid` always returns the type of the interface, An undocumented features, which is very misleading as for classes it returns the 'most derived type' (http://dlang.org/expression.html#TypeidExpression)
>>
>> For example:
>>
>> import std.stdio;
>>
>> interface A {
>>
>> }
>>
>> class B : A {
>>     int y;
>> }
>>
>> void foo(A a) {
>>     writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(a), a);
>> }
>>
>> void main() {
>>     auto b = new B();
>>     writefln("Original scope got 'b' of typeid(%s) which is really '%s'", typeid(b), b);
>>     foo(b);
>> }
>>
>> would print:
>>
>> Original scope got 'b' of typeid(test.B) which is really 'test.B'
>> foo got 'a' of typeid(test.A) which is really 'test.B'
>>
>> (notice that '%s' in the format correctly identifies 'a' to be of type 'B' in the same time that the typeid expression recognizes 'a' as of type 'A')
>>
>> Rewriting foo as:
>>
>> void foo(A a) {
>>     writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(cast(Object)a), a);
>> }
>>
>> solves the issue (Thanks to David Nadlinger)
>>
>> I must say I find this very counter-intuitive as its VERY LIKELY to have an interface as the polymorphic instance and sometimes you would want to query its exact type.
>>
>> Obviously `typeid` can infer that 'a' is really an `Object` and then infer that its of type `B` (just as the writefln managed to).
>> This leads me the conclusion that `typeid` is only half-baked and can be improved to support interfaces in a more intuitive manner.
>>
>> Any reasons why it inherently can't be improved to do so?
>>
>> Thanks.
> 
> Maybe this is because the compiler is computing the typeid at runtime? This is because a is of type A! It's clearly stated in the signature:
> 
> 
> void foo(A a)
> {
>      writefln("foo got 'a' of typeid(%s) which is really '%s'", typeid(a), a);
> }
> 
> typeid(a) looks at the type of a and see's A and hence that is what it is "locally"(it mistakenly evaluates typeid because it does not realize that a could be any B : A).
> 
> If typeid(cast(Object)a) produces a different result then clearly dmd is doing something wrong.

You are answering a nearly 3-year-old thread. I don't know if he cares any more ;)

-Steve