[Issue 24892] New: We need a __traits trait to test for whether one class is derived from another
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Dec 6 02:20:06 UTC 2024
https://issues.dlang.org/show_bug.cgi?id=24892
Issue ID: 24892
Summary: We need a __traits trait to test for whether one class
is derived from another
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: enhancement
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: issues.dlang at jmdavisProg.com
Right now, the normal way to test that one class is derived from another is to
do is(T : U), which does not technically test whether T is derived from U.
Rather, it tests whether T implicitly converts to U, which happens to be true
when T is derived from U. However, it can also be true thanks to alias this,
e.g.
```
void main()
{
auto foo = new Foo;
A a = foo;
static assert(is(Foo : A));
}
class A {}
class Foo
{
A a;
alias this = a;
}
```
compiles just fine even though Foo is not derived from A. And technically, it's
even possible for is(T : U) and is(U : T) to both be true at the same time
(whether inheritance is involved or not).
As such, we really need to stop testing for inheritance via testing for
implicit conversion. While it works most of the time, it is actually wrong and
can cause bugs.
There _might_ be some clever way to test whether one class is derived from
another by checking whether alias this exists for the class and whether the
alias this implicitly converts to the target type in order to exclude it, but
then you have the issue that it's possible for the alias this to convert to one
of the class' actual base classes, so excluding it could give the wrong answer.
As such, I'm not aware of any way to properly test whether a class is actually
derived from another - and if it does exist, it's likely to involve several
tests when it should just be a simple question.
As such, I would propose that we add something to __traits to provide this
information (either that or add something new to is expressions which
explicitly tests for it separate from testing for implicit conversions). For
instance, we could have __traits(isDerivedFrom, T, U).
Now, that also raises the question of how interfaces should be handled, since
arguably, a class is not derived from an interface (rather, it implements it).
So, we could also add something like __traits(implements, T, U) - or we could
just have __traits(isDerivedFrom, T, U) handle both classes and interfaces and
then use is(U == interface) and is(U == class) to distinguish. That being said,
separate traits seems simpler, and it makes it so that you don't accidentally
treat a class as an interface or vice versa, so that's what I'd vote for.
In either case, given that we're not planning to get rid of alias this and that
it seems to make it impossible to properly test whether one class is derived
from another, I really think that we should add a way to explicitly test for
inheritance to the language, and then we can start using that instead of is(T :
U).
--
More information about the Digitalmars-d-bugs
mailing list