Skip to content

Commit

Permalink
Fix requirement candidate lookup to prefer decls in the same paraent …
Browse files Browse the repository at this point in the history
…as the inheritance decl. (#5965)
  • Loading branch information
csyonghe authored Dec 31, 2024
1 parent 89dd2b1 commit 88e221b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 2 deletions.
4 changes: 3 additions & 1 deletion source/core/slang-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ class List
}
}

inline void swapElements(T* vals, Index index1, Index index2)
inline static void swapElements(T* vals, Index index1, Index index2)
{
if (index1 != index2)
{
Expand All @@ -547,6 +547,8 @@ class List
}
}

inline void swapElements(Index index1, Index index2) { swapElements(m_buffer, index1, index2); }

template<typename T2, typename Comparer>
Index binarySearch(const T2& obj, Comparer comparer) const
{
Expand Down
20 changes: 19 additions & 1 deletion source/slang/slang-check-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6541,7 +6541,25 @@ bool SemanticsVisitor::findWitnessForInterfaceRequirement(
}
}
}

if (lookupResult.isOverloaded())
{
// If we found multiple members with the same name,
// we want to move the declarations in the same parent as inheritanceDecl
// to the front of the list, so that we always consider them first instead of
// the members declared in other extension decls.
//
Index front = 0;
auto parentOfInheritanceDecl = getParentAggTypeDeclBase(inheritanceDecl);
for (Index i = 0; i < lookupResult.items.getCount(); i++)
{
if (getParentAggTypeDeclBase(lookupResult.items[i].declRef.getDecl()) ==
parentOfInheritanceDecl)
{
lookupResult.items.swapElements(i, front);
front++;
}
}
}
// Iterate over the members and look for one that matches
// the expected signature for the requirement.
for (auto member : lookupResult)
Expand Down
12 changes: 12 additions & 0 deletions source/slang/slang-syntax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,18 @@ Decl* getParentAggTypeDecl(Decl* decl)
return nullptr;
}

Decl* getParentAggTypeDeclBase(Decl* decl)
{
decl = decl->parentDecl;
while (decl)
{
if (as<AggTypeDeclBase>(decl))
return decl;
decl = decl->parentDecl;
}
return nullptr;
}

Decl* getParentFunc(Decl* decl)
{
while (decl)
Expand Down
1 change: 1 addition & 0 deletions source/slang/slang-syntax.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ Module* getModule(Decl* decl);
/// Get the parent decl, skipping any generic decls in between.
Decl* getParentDecl(Decl* decl);
Decl* getParentAggTypeDecl(Decl* decl);
Decl* getParentAggTypeDeclBase(Decl* decl);
Decl* getParentFunc(Decl* decl);

} // namespace Slang
Expand Down
43 changes: 43 additions & 0 deletions tests/language-feature/interfaces/overloaded-associatedtype.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK): -output-using-type

interface IFoo<T> {
associatedtype Output : IBar;
func foo(other: T) -> Output;
}

interface IBar { int getId(); }

struct Ant:IBar { int getId() { return 0; } };
struct Bat:IBar { int getId() { return 1; } };
struct Cat:IBar { int getId() { return 2; } };
struct Dog:IBar { int getId() { return 3; } };
struct Ewe:IBar { int getId() { return 4; } };
struct Fox:IBar { int getId() { return 5; } };
struct Gnu:IBar { int getId() { return 6; } };

extension Ant: IFoo<Bat> {
typedef Cat Output;
func foo(other: Bat) -> Cat { return Cat(); }
}
extension Ant: IFoo<Dog> {
typedef Ewe Output;
func foo(other: Dog) -> Ewe { return Ewe(); }
}
extension Ant: IFoo<Fox> {
typedef Gnu Output;
func foo(other: Fox) -> Gnu { return Gnu(); }
}

int test<T:IFoo<Fox>>(T v) {
return v.foo(Fox()).getId();
}

//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=output
RWStructuredBuffer<int> output;

[numthreads(1,1,1)]
void computeMain() {
Ant a;
// CHECK: 6
output[0] = test(a);
}

0 comments on commit 88e221b

Please sign in to comment.