Skip to content

Commit

Permalink
Merge pull request #7959 from RazvanN7/Issue_17373
Browse files Browse the repository at this point in the history
Fix Issue 17373 -  traits getOverloads + multiple interface inheritan…
merged-on-behalf-of: Mike Franklin <JinShil@users.noreply.github.com>
  • Loading branch information
dlang-bot authored Apr 24, 2018
2 parents e14a50f + 56e85cc commit 1848c70
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
55 changes: 52 additions & 3 deletions src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,33 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
ex = dve.e1;
}

overloadApply(f, (Dsymbol s)
bool[string] funcTypeHash;

/* Compute the function signature and insert it in the
* hashtable, if not present. This is needed so that
* traits(getOverlods, F3, "visit") does not count `int visit(int)`
* twice in the following example:
*
* =============================================
* interface F1 { int visit(int);}
* interface F2 { int visit(int); void visit(); }
* interface F3 : F2, F1 {}
*==============================================
*/
void insertInterfaceInheritedFunction(FuncDeclaration fd, Expression e)
{
auto funcType = fd.type.toChars();
auto len = strlen(funcType);
string signature = funcType[0 .. len].idup;
//printf("%s - %s\n", fd.toChars, signature);
if (signature !in funcTypeHash)
{
funcTypeHash[signature] = true;
exps.push(e);
}
}

int dg(Dsymbol s)
{
auto fd = s.isFuncDeclaration();
if (!fd)
Expand All @@ -941,9 +967,32 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
auto e = ex ? new DotVarExp(Loc.initial, ex, fa, false)
: new DsymbolExp(Loc.initial, fa, false);

exps.push(e);
// if the parent is an interface declaration
// we must check for functions with the same signature
// in different inherited interfaces
if (sym.isInterfaceDeclaration())
insertInterfaceInheritedFunction(fd, e);
else
exps.push(e);
return 0;
});
}

InterfaceDeclaration ifd = null;
if (sym)
ifd = sym.isInterfaceDeclaration();
// If the symbol passed as a parameter is an
// interface that inherits other interfaces
if (ifd && ifd.interfaces)
{
// check the overloads of each inherited interface individually
foreach (bc; ifd.interfaces)
{
if (auto fd = bc.sym.search(e.loc, f.ident))
overloadApply(fd, &dg);
}
}
else
overloadApply(f, &dg);

auto tup = new TupleExp(e.loc, exps);
return tup.expressionSemantic(scx);
Expand Down
20 changes: 20 additions & 0 deletions test/runnable/test17373.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
interface Foo { void visit (int); }
interface Bar { void visit(double); }
interface FooBar : Foo, Bar {}
static assert(__traits(getOverloads, FooBar, "visit").length == 2);

interface Fbar { void visit(char); void visit(double); }
interface Triple : Foo, Bar, Fbar {}
static assert(__traits(getOverloads, Triple, "visit").length == 3);

interface InheritanceMadness : FooBar, Triple {}
static assert(__traits(getOverloads, Triple, "visit").length == 3);

interface Simple
{
int square(int);
real square(real);
}
static assert(__traits(getOverloads, Simple, "square").length == 2);

void main() {}

0 comments on commit 1848c70

Please sign in to comment.