Skip to content

Loading…

Issue 7829 - Function traits should be usable with subtyping #1445

Closed
wants to merge 1 commit into from

2 participants

@ghost

http://d.puremagic.com/issues/show_bug.cgi?id=7829

Perhaps this should also apply to some other traits, for now I've included only function traits.

@9rnsr
D Programming Language member

This change would not work if there are two or more level of alias this.

class C { int foo() {} alias n this; }
struct S1 { C c; alias c this; }
struct S2 { S1 s; alias s this; }
void main() { static assert(!__traits(isVirtualFunction, S2.foo)); }
@ghost ghost closed this
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 62 additions and 5 deletions.
  1. +27 −5 src/traits.c
  2. +35 −0 test/runnable/traits.d
View
32 src/traits.c
@@ -108,6 +108,28 @@ Expression *TraitsExp::semantic(Scope *sc)
goto Lfalse; \
goto Ltrue;
+#define ISVARDSYMBOL(cond) \
+ for (size_t i = 0; i < dim; i++) \
+ { \
+ Expression *e; \
+ Dsymbol *s = getDsymbol((*args)[i]); \
+ if ((s = getDsymbol((*args)[i])) != NULL) \
+ { } \
+ else if ((e = isExpression((*args)[i])) != NULL) \
+ { \
+ if (e->op == TOKvar) \
+ s = ((VarExp *)e)->var; \
+ else if (e->op == TOKdotvar) \
+ s = ((DotVarExp *)e)->var; \
+ } \
+ if (!s) \
+ goto Lfalse; \
+ if (!(cond)) \
+ goto Lfalse; \
+ } \
+ if (!dim) \
+ goto Lfalse; \
+ goto Ltrue; \
if (ident == Id::isArithmetic)
@@ -171,28 +193,28 @@ Expression *TraitsExp::semantic(Scope *sc)
else if (ident == Id::isAbstractFunction)
{
FuncDeclaration *f;
- ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
+ ISVARDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
}
else if (ident == Id::isVirtualFunction)
{
FuncDeclaration *f;
- ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
+ ISVARDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
}
else if (ident == Id::isVirtualMethod)
{
FuncDeclaration *f;
- ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod())
+ ISVARDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod())
}
else if (ident == Id::isFinalFunction)
{
FuncDeclaration *f;
- ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
+ ISVARDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
}
#if DMDV2
else if (ident == Id::isStaticFunction)
{
FuncDeclaration *f;
- ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested())
+ ISVARDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested())
}
else if (ident == Id::isRef)
{
View
35 test/runnable/traits.d
@@ -967,6 +967,40 @@ void test5978() {
/*************************************************************/
+template Tuple7829(TL...) { alias TL Tuple7829; }
+
+void test7829()
+{
+ class C
+ {
+ final void fvf() { }
+ void vf() { }
+ void vm() { }
+ abstract void af();
+ final void ff() { }
+ static void sf() { }
+ }
+
+ static struct S
+ {
+ void nvf() { }
+ C c;
+ alias c this;
+ }
+
+ S s;
+ foreach (sym; Tuple7829!(S, s))
+ {
+ static assert(!__traits(isVirtualFunction, sym.nvf));
+ static assert(__traits(isVirtualFunction, sym.fvf));
+ static assert(__traits(isVirtualFunction, sym.vf));
+ static assert(__traits(isVirtualMethod, sym.vm));
+ static assert(__traits(isAbstractFunction, sym.af));
+ static assert(__traits(isFinalFunction, sym.ff));
+ static assert(__traits(isStaticFunction, sym.sf));
+ }
+}
+
int main()
{
test1();
@@ -996,6 +1030,7 @@ int main()
test7608();
test7858();
test5978();
+ test7829();
writeln("Success");
return 0;
Something went wrong with that request. Please try again.