From ddd29057e48a5b309726750e3daf78bfd073038e Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 4 Sep 2024 13:25:37 -0700 Subject: Fix extension override behavior, and disallow extension on interface types. (#4977) * Add a test to ensure extension does not override existing conformance. * Fix doc. * Update documentation. * Fix doc. * Add diagnostic test. --- source/slang/slang-check-overload.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'source/slang/slang-check-overload.cpp') diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index 6d376dba3..0e01eeed2 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -1187,6 +1187,16 @@ namespace Slang return CountParameters(parentGeneric).required; } + DeclRef getParentDeclRef(DeclRef declRef) + { + auto parent = declRef.getParent(); + while (parent.as()) + { + parent = parent.getParent(); + } + return parent; + } + int SemanticsVisitor::CompareLookupResultItems( LookupResultItem const& left, LookupResultItem const& right) @@ -1204,13 +1214,31 @@ namespace Slang // directly (it is only visible through the requirement witness // information for inheritance declarations). // - auto leftDeclRefParent = left.declRef.getParent(); - auto rightDeclRefParent = right.declRef.getParent(); + auto leftDeclRefParent = getParentDeclRef(left.declRef); + auto rightDeclRefParent = getParentDeclRef(right.declRef); bool leftIsInterfaceRequirement = isInterfaceRequirement(left.declRef.getDecl()); bool rightIsInterfaceRequirement = isInterfaceRequirement(right.declRef.getDecl()); if(leftIsInterfaceRequirement != rightIsInterfaceRequirement) return int(leftIsInterfaceRequirement) - int(rightIsInterfaceRequirement); + // Prefer non-extension declarations over extension declarations. + bool leftIsExtension = as(leftDeclRefParent.getDecl()) != nullptr; + bool rightIsExtension = as(rightDeclRefParent.getDecl()) != nullptr; + if (leftIsExtension != rightIsExtension) + { + return int(leftIsExtension) - int(rightIsExtension); + } + else if (leftIsExtension) + { + // If both are declared in extensions, prefer the one that is least generic. + bool leftIsGeneric = leftDeclRefParent.getParent().as() != nullptr; + bool rightIsGeneric = rightDeclRefParent.getParent().as() != nullptr; + if (leftIsGeneric != rightIsGeneric) + { + return int(leftIsGeneric) - int(rightIsGeneric); + } + } + // Any decl is strictly better than a module decl. bool leftIsModule = (as(left.declRef) != nullptr); bool rightIsModule = (as(right.declRef) != nullptr); -- cgit v1.2.3