digitalmars.D - Identity of interfaces (or not)
- Tomas Lindquist Olsen (59/59) Dec 02 2008 Hi all.
- Frits van Bommel (16/55) Dec 02 2008 It's also available from
- BCS (7/17) Dec 02 2008 why not make
- Frits van Bommel (2/15) Dec 02 2008 Because he's talking about 'is', not '=='?
- BCS (2/19) Dec 02 2008 ok `s/==/is/` now?
- Christopher Wright (3/16) Dec 02 2008 That makes sense, and I fully support it. I tend to use interfaces
- Robert Fraser (2/7) Dec 02 2008 I like, but will this work for COM?
- BCS (5/14) Dec 03 2008 All that would be required is to define casting a non D Com object to Ob...
- Jason House (3/8) Dec 03 2008 Interfaces are not always castable to Object. At a minimum, it fails fo...
- BCS (3/13) Dec 03 2008 Check my reply to Robert. I think it works if you just do it and ignore ...
Hi all. I've spent that last weeks rewriting LDC's handling handling of struct/union/class/interface to match DMD, in terms of datalayout, ABI and correctness in general. It's done now, and seems to be working well, however, running DStress on the latest revision, a new regression showed up! Test case: http://dsource.org/projects/dstress/browser/run/opIdentity_01.d Original NG post with issue: http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D.bugs&artnum=2676 I've failed to find any replies to the thread so I'm unsure if this test is even valid. I'll paste the test case from DStress here as well: <code> module dstress.run.opIdentity_01; interface I { I parent(); void parent(I i); void addChild(I i); } interface J : I { } class A : I { private I myParent; void addChild(I i) { i.parent = this; } I parent() { return myParent; } void parent(I parent) { myParent = parent; } } class B : A, J { } int main() { J a = new B; J b = new B; a.addChild(b); if(!(b.parent is a)){ // FAILS assert(0); } return 0; } </code> Here's the problem. DMD and (now) LDC both compile this test fine, but it fails at runtime on the marked line. The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question. The easiest way I can see to make this work, would be to disable static "downcasts" to interfaces, this way, in A.addChild, when 'this' is converted to I, it would have to look through the ClassInfo and would always use the same vtable for a single interface. The other would be to change the ABI... But, I'm not even sure if this is a bug or if D interfaces just work this way, I've not been able to find much information... So is it a bug? Or is identity for interfaces simply not guaranteed to pass, even when it's the same Object in question? Thanx - Tomas
Dec 02 2008
Tomas Lindquist Olsen wrote:Hi all. I've spent that last weeks rewriting LDC's handling handling of struct/union/class/interface to match DMD, in terms of datalayout, ABI and correctness in general. It's done now, and seems to be working well, however, running DStress on the latest revision, a new regression showed up! Test case: http://dsource.org/projects/dstress/browser/run/opIdentity_01.d Original NG post with issue: http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmar .D.bugs&artnum=2676For what it's worth: both DMD and GDC also fail that test.I've failed to find any replies to the thread so I'm unsure if this test is even valid.It's also available from <http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.bu s&article_id=2676>, which shows that there were replies. Unfortunately, webnews is broken so if you click any of the links you need to edit the URL (s/digitalmars.d/digitalmars.d.bugs/).I'll paste the test case from DStress here as well:[snip]Here's the problem. DMD and (now) LDC both compile this test fine, but it fails at runtime on the marked line. The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question. The easiest way I can see to make this work, would be to disable static "downcasts" to interfaces, this way, in A.addChild, when 'this' is converted to I, it would have to look through the ClassInfo and would always use the same vtable for a single interface. The other would be to change the ABI... But, I'm not even sure if this is a bug or if D interfaces just work this way, I've not been able to find much information... So is it a bug? Or is identity for interfaces simply not guaranteed to pass, even when it's the same Object in question?Yeah, the only way to "fix" it would be to make *all* interface->interface casts *implicitly* dynamic, even though the compiler *knows* a way to get a correct I statically. However I don't think that's a good idea. I'd say that if you really want interfaces to compare equal with 'is' you need to (1) make sure no object implements any interface more than once, or (2) cast to Object before comparing any interface that is multiply-implemented.
Dec 02 2008
Reply to Tomas,The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?So is it a bug? Or is identity for interfaces simply not guaranteed to pass, even when it's the same Object in question? Thanx - Tomas
Dec 02 2008
BCS wrote:Reply to Tomas,Because he's talking about 'is', not '=='?The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?
Dec 02 2008
Reply to Frits,BCS wrote:ok `s/==/is/` now?Reply to Tomas,Because he's talking about 'is', not '=='?The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?
Dec 02 2008
BCS wrote:Reply to Tomas,That makes sense, and I fully support it. I tend to use interfaces rather often, and anything to improve support for them is good.The problem is that B has two vtables that implement the interface I. However, in A.addChild, i.parent get's the first one (introduced by A), and in main, it gets the second one (J , which derived from I). The identity check then fails because the pointers aren't the same, even though it's the same object in question.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?
Dec 02 2008
BCS wrote:why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?I like, but will this work for COM?
Dec 02 2008
Reply to Robert,BCS wrote:All that would be required is to define casting a non D Com object to Object as something rational and consistent (but only in the special cases of this test). I think this should be easy to do as all it would require, as a result of both how COM and D interfaces work, is using an unchecked cast to object.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?I like, but will this work for COM?
Dec 03 2008
BCS wrote:why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?Interfaces are not always castable to Object. At a minimum, it fails for COM and extern(C++)
Dec 03 2008
Reply to Jason,BCS wrote:Check my reply to Robert. I think it works if you just do it and ignore some types of errors. It's under the hood anyway.why not make Ia == Ib into cast(Object)Ia == cast(Object)Ib ?Interfaces are not always castable to Object. At a minimum, it fails for COM and extern(C++)
Dec 03 2008