Jump to page: 1 2
Thread overview
[Issue 14612] typeid(interface) returns TypeInfo_Class object
Jun 02, 2015
Kenji Hara
Jul 05, 2015
Rainer Schuetze
Jul 09, 2015
Kenji Hara
Jul 10, 2015
Rainer Schuetze
Jul 21, 2015
Kenji Hara
Jul 21, 2015
Kenji Hara
Jul 21, 2015
Kenji Hara
Jul 22, 2015
Rainer Schuetze
Jul 22, 2015
Rainer Schuetze
Aug 03, 2015
Kenji Hara
Dec 17, 2022
Iain Buclaw
June 02, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> ---
(In reply to Kenji Hara from comment #0)
> 2. Separate ClassInfo from TypeInfo_Class again and define TypeInfo hierarchy as follows:
> 
> abstract class ClassInfo : TypeInfo { ... }
> class TypeInfo_Class : ClassInfo { ... }
> class TypeInfo_Interface : ClassInfo { ... }
> 
> Pros: By handling ClassInfo, the runtime cost in dynamic cast operation can
> be kept same with today's.
> Cons: If an user still using the name 'ClassInfo', the code behavior will be
> changed.

Implemented: https://github.com/D-Programming-Language/dmd/pull/4711 https://github.com/D-Programming-Language/druntime/pull/1295

--
July 05, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

Rainer Schuetze <r.sagitario@gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |r.sagitario@gmx.de

--- Comment #2 from Rainer Schuetze <r.sagitario@gmx.de> ---
The language spec says for both typeid() and .classinfo that the dynamic type is returned. For classinfo, it says ".classinfo applied to an interface gives the information for the interface, not the class it might be an instance of." which makes it a compile time property for interfaces. I could not find a spec for typeid regarding interfaces.

I suspect they are supposed to be the same. That means typeid(i) and
i.classinfo should evaluate to typeid(I). This must be generated by the
compiler.

Actually I think the semantics are pretty arbitrary and not intuitive. Why
would anyone expect J to be the correct type? I'd rather prefer if both classes
and interfaces would return the dynamic type, i.e. typeid(D). You can get the
static type of an expression by using typeid(typeof(i)).

--
July 09, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #3 from Kenji Hara <k.hara.pg@gmail.com> ---
(In reply to Rainer Schuetze from comment #2)
> The language spec says for both typeid() and .classinfo that the dynamic type is returned. For classinfo, it says ".classinfo applied to an interface gives the information for the interface, not the class it might be an instance of." which makes it a compile time property for interfaces. I could not find a spec for typeid regarding interfaces.
>
> I suspect they are supposed to be the same. That means typeid(i) and
> i.classinfo should evaluate to typeid(I). This must be generated by the
> compiler.

It's correct. typeid(obj) and obj.classinfo are just same thing in
implementation level.

> Actually I think the semantics are pretty arbitrary and not intuitive. Why
> would anyone expect J to be the correct type? I'd rather prefer if both
> classes and interfaces would return the dynamic type, i.e. typeid(D). You
> can get the static type of an expression by using typeid(typeof(i)).

I don't know why so, but I guess it might be the dynamic cast cost.

The current behavior, getting actual interface information (== classinfo) can
be done with a trivial pointer (== class/interface reference) adjustment.

On the other hand, a dynamic cast  from interface to class needs more cost.
1. getting the interface information
2. downcast and get Object reference from the interface reference by using the
information.
3. get the actual typeinfo from the Object reference.

And you can do the latter behavior by typeid(cast(Object)obj). I feel that
syntactic cost is enough small.

In short, the orthogonality may have been priority than the intuitive, but complex behavior.

--
July 10, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #4 from Rainer Schuetze <r.sagitario@gmx.de> ---
> And you can do the latter behavior by typeid(cast(Object)obj).
> I feel that syntactic cost is enough small.

cast(Object) creates a call into the runtime (_d_interface_cast) and is pretty
expensive. It could be optimized to the series of indirections by the compiler,
though.

> In short, the orthogonality may have been priority than the intuitive, but complex behavior.

The "complex" behaviour costs just an additional reading of an offset to the object base address, very much what a thunk does when calling a virtual function.

I guess the current behaviour could be described as "typeid(I) evaluates to the most derived interface that is implemented by the object and that inherits from the static type."

But "most derived" is not well defined when it comes to inheriting from multiple interfaces:

import std.stdio;

interface I {}
interface J : I {}
interface K : I {}
class E : J, K {}

void main()
{
    E e = new E;
    J j = e;
    K k = e;
    I ij = j;
    I ik = k;
    writeln(typeid(ij));      // prints 'test.J' !?
    writeln(typeid(ik));      // prints 'test.K' !?
}

--
July 21, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #5 from Kenji Hara <k.hara.pg@gmail.com> ---
(In reply to Rainer Schuetze from comment #4)
> cast(Object) creates a call into the runtime (_d_interface_cast) and is
> pretty expensive. It could be optimized to the series of indirections by the
> compiler, though.

Actually _d_interface_cast is not so high cost so Object has no base class and implements no interfaces.

> I guess the current behaviour could be described as "typeid(I) evaluates to the most derived interface that is implemented by the object and that inherits from the static type."
> 
> But "most derived" is not well defined when it comes to inheriting from multiple interfaces:

It would be visible when you consider the class object layout.

> interface I {}
> interface J : I {}
> interface K : I {}
> class E : J, K {}

//      I   I
// E :  J,  K
//===============

//      ij  ik
//      |   |
//      j   k
//      |   |
// e --[x]-[y]

[x] is the "most derived vptr slot of ij, and [y] is of ik.

--
July 21, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #6 from Kenji Hara <k.hara.pg@gmail.com> ---
Anyway, the downcast behavior is not a part of the suggested issue. It should go an enhancement report.

--
July 21, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #7 from Kenji Hara <k.hara.pg@gmail.com> ---
(In reply to Rainer Schuetze from comment #4)
> But "most derived" is not well defined when it comes to inheriting from multiple interfaces:

I found an existing report:
Issue 13833 - .classinfo.name (and typeid(obj)) does not print proper dynamic
type when using an interface

--
July 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #8 from Rainer Schuetze <r.sagitario@gmx.de> ---
> Actually _d_interface_cast is not so high cost so Object has no base class and implements no interfaces.

It's still a lot more than just a null check and reading a vtbl entry an
another indirection.
If the instance is from a deeply derived class, _d_interface_cast walks through
all base classes to find Object.

--
July 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #9 from Rainer Schuetze <r.sagitario@gmx.de> ---
> [x] is the "most derived vptr slot of ij, and [y] is of ik.

But if all you have is a pointer to I that's not very deterministic.

--
August 03, 2015
https://issues.dlang.org/show_bug.cgi?id=14612

--- Comment #10 from Kenji Hara <k.hara.pg@gmail.com> ---
I found slightly related issue tickets:

Issue 4979 - Implementing an interface twice results in different a reference
for each interface
Issue 11683 - Document current Identity Expression over `interface`s behaviour

--
« First   ‹ Prev
1 2