summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-overload.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-06-11 12:12:53 -0700
committerGitHub <noreply@github.com>2025-06-11 12:12:53 -0700
commit45560483447dd737a63efc236b2be07fd0fc4347 (patch)
treed0bc2e90d3aa0bfb630e02789ad6d38986cbc2a6 /source/slang/slang-check-overload.cpp
parent5a851fe846bb4b3657dfc94a88fcce7b1221a8eb (diff)
Fix an issue in extension override. (#7402)
* Fix an issue in extension override. * Fix typo in comment.
Diffstat (limited to 'source/slang/slang-check-overload.cpp')
-rw-r--r--source/slang/slang-check-overload.cpp32
1 files changed, 28 insertions, 4 deletions
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp
index 8fbdceabb..8d76d2554 100644
--- a/source/slang/slang-check-overload.cpp
+++ b/source/slang/slang-check-overload.cpp
@@ -1321,6 +1321,34 @@ int SemanticsVisitor::CompareLookupResultItems(
LookupResultItem const& left,
LookupResultItem const& right)
{
+ auto leftDeclRefParent = getParentDeclRef(left.declRef);
+ auto rightDeclRefParent = getParentDeclRef(right.declRef);
+
+ bool leftIsExtension = false;
+ bool rightIsExtension = false;
+ bool leftIsFreeFormExtension = false;
+ bool rightIsFreeFormExtension = false;
+
+ // Prefer declarations that are not in free-form generic extensions, i.e.
+ // `extension<T:IFoo> T { /* declaration here should have lower precedence. */ }
+ if (auto leftExt = as<ExtensionDecl>(leftDeclRefParent.getDecl()))
+ {
+ leftIsExtension = true;
+ if (isDeclRefTypeOf<GenericTypeParamDeclBase>(leftExt->targetType))
+ leftIsFreeFormExtension = true;
+ }
+ if (auto rightExt = as<ExtensionDecl>(rightDeclRefParent.getDecl()))
+ {
+ rightIsExtension = true;
+ if (isDeclRefTypeOf<GenericTypeParamDeclBase>(rightExt->targetType))
+ rightIsFreeFormExtension = true;
+ }
+
+ // If one of the candidates is a free-form extension, it is always worse than
+ // a non-free-form extension.
+ if (leftIsFreeFormExtension != rightIsFreeFormExtension)
+ return int(leftIsFreeFormExtension) - int(rightIsFreeFormExtension);
+
// It is possible for lookup to return both an interface requirement
// and the concrete function that satisfies that requirement.
// We always want to favor a concrete method over an interface
@@ -1334,16 +1362,12 @@ int SemanticsVisitor::CompareLookupResultItems(
// directly (it is only visible through the requirement witness
// information for inheritance declarations).
//
- 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)
{
// Add a special case for constructors, where we prefer the one that is not synthesized,