diff options
| author | Yong He <yonghe@outlook.com> | 2024-09-04 13:25:37 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-04 13:25:37 -0700 |
| commit | ddd29057e48a5b309726750e3daf78bfd073038e (patch) | |
| tree | a054b99acb87d61ef4818dce5fa837ccfd050288 /source/slang/slang-check-overload.cpp | |
| parent | 56a3c028a6725e13a2ae3a724eaee05ad9f4802a (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.cpp | 32 |
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); |
