www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - why is `typeid` only half baked?

reply Or Dahan <mailordahan gmail.com> writes:
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.
Nov 06 2015
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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.
Nov 06 2015
next sibling parent Jacob Carlborg <doob me.com> writes:
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
Nov 06 2015
prev sibling parent reply Or Dahan <mailordahan gmail.com> writes:
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?
Nov 09 2015
parent Adam D. Ruppe <destructionator gmail.com> writes:
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.
Nov 09 2015
prev sibling parent reply Mr.Bingo <Bingo Namo.com> writes:
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.
Jun 30 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Jun 30 2018