summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-overload.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-09-04 13:25:37 -0700
committerGitHub <noreply@github.com>2024-09-04 13:25:37 -0700
commitddd29057e48a5b309726750e3daf78bfd073038e (patch)
treea054b99acb87d61ef4818dce5fa837ccfd050288 /source/slang/slang-check-overload.cpp
parent56a3c028a6725e13a2ae3a724eaee05ad9f4802a (diff)
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.
Diffstat (limited to 'source/slang/slang-check-overload.cpp')
-rw-r--r--source/slang/slang-check-overload.cpp32
1 files changed, 30 insertions, 2 deletions
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<Decl> getParentDeclRef(DeclRef<Decl> declRef)
+ {
+ auto parent = declRef.getParent();
+ while (parent.as<GenericDecl>())
+ {
+ 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<ExtensionDecl>(leftDeclRefParent.getDecl()) != nullptr;
+ bool rightIsExtension = as<ExtensionDecl>(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<GenericDecl>() != nullptr;
+ bool rightIsGeneric = rightDeclRefParent.getParent().as<GenericDecl>() != nullptr;
+ if (leftIsGeneric != rightIsGeneric)
+ {
+ return int(leftIsGeneric) - int(rightIsGeneric);
+ }
+ }
+
// Any decl is strictly better than a module decl.
bool leftIsModule = (as<ModuleDeclarationDecl>(left.declRef) != nullptr);
bool rightIsModule = (as<ModuleDeclarationDecl>(right.declRef) != nullptr);