diff options
| author | Yong He <yonghe@outlook.com> | 2025-06-11 12:12:53 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-11 12:12:53 -0700 |
| commit | 45560483447dd737a63efc236b2be07fd0fc4347 (patch) | |
| tree | d0bc2e90d3aa0bfb630e02789ad6d38986cbc2a6 /source/slang/slang-check-overload.cpp | |
| parent | 5a851fe846bb4b3657dfc94a88fcce7b1221a8eb (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.cpp | 32 |
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, |
