Should "a is b" compile if a and b have unrelated classes?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Apr 10 22:56:31 UTC 2018


On Tuesday, April 10, 2018 21:52:22 Michael Coulombe via Digitalmars-d-learn 
wrote:
> I had a bug in my code that was messing me up for a while, and it
> boiled down to an identity check between two Object references
> with unrelated static types, like below:
>
> class A {}
> class B {}
> void main() {
>      A a = new A;
>      B b = new B;
>      if (a is b) {} // compiles
> }
>
> I was surprised that the type system failed me here. It's true
> that A and B could be upcast to Object and then comparisons would
> make sense type-wise, but the comparison should never pass (and
> the compiler should know it won't since they are in separate
> inheritance subtrees) unless the programmer is intentionally
> breaking the type system.
>
> Is there reasoning for this? If not, should it be a warning or
> error, as it is for example when comparing two pointers to
> structs of different types?

Well, the compiler can't simply say that they're different classes and
refuse to compare their references. It could look at the class hierarchy and
determine that there's no way that the two are the same reference, because
neither A nor B is a subclass of the other and thus treat it as an error -
which I gather is what you're suggesting it should do. However, because
doing that is more complicated, I suspect that it just doesn't bother. With
struct pointers, it can at least see at a glance that one can't be the
other, whereas it has to do a lot more examination of the type if it's class
references.

It's probably a reasonable enhancement request, though I'm not sure that it
really matters much. One potential issue is that since opEquals is
unfortunately part of Object, it's perfectly legal to do

    if(a == b)

even though a and b can never be equal, so if is were disallowed in this
case, then we'd get a situation where a == b compiles but a is b doesn't
which would be a bit weird - though presumably, if we do end up going with
some form of Andrei's ProtoObject proposal where we get a new root class
beneath Object, then we'd definitely have classes that could be compared
with is but not ==. So, that may not be all that big a deal as weird as it
may be.

My bigger concern would be how it would interact with generic code. It's not
uncommon that stuff that at first glance seems like it should be disallowed
would actually cause a fair but of grief in generic code (e.g. that's at
least part of why it's usually the case that function attributes that don't
apply are just ignored rather than treated as errors). If it definitely
wasn't going to cause problems for generic code, then such a change would
probably be reasonable, but I have no idea how likely it would be to cause
problems in generic code.

So, maybe? You can certainly open an enhancement request about it.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list