summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-08-06 01:07:41 -0700
committerGitHub <noreply@github.com>2025-08-06 08:07:41 +0000
commit68b0125226464cb3c9e9b7f50bfb53cda97723b4 (patch)
tree5f0833c6d9aa759b2769f7f6ac9b3ca6ed9a10f0 /source/slang
parent83675103a1a4fefde11b314aed26f4d37860efe7 (diff)
Add reflection api for overload candidate filtering. (#8066)
* Add reflection api for overload candidate filtering. * Fix API. * Fix. * Update build. * Update test. * Update formatting.
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-ast-expr.h2
-rw-r--r--source/slang/slang-ast-iterator.h2
-rw-r--r--source/slang/slang-check-expr.cpp16
-rw-r--r--source/slang/slang-check-overload.cpp4
-rw-r--r--source/slang/slang-language-server-ast-lookup.cpp2
-rw-r--r--source/slang/slang-language-server.cpp8
-rw-r--r--source/slang/slang-linkable.cpp59
-rw-r--r--source/slang/slang-linkable.h1
-rw-r--r--source/slang/slang-reflection-api.cpp40
9 files changed, 93 insertions, 41 deletions
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
index 1100cdee4..32c724e10 100644
--- a/source/slang/slang-ast-expr.h
+++ b/source/slang/slang-ast-expr.h
@@ -79,7 +79,7 @@ class OverloadedExpr2 : public Expr
Expr* base = nullptr;
// The lookup result that was ambiguous
- List<Expr*> candidiateExprs;
+ List<Expr*> candidateExprs;
};
FIDDLE(abstract)
diff --git a/source/slang/slang-ast-iterator.h b/source/slang/slang-ast-iterator.h
index 3cce8df59..c29a42665 100644
--- a/source/slang/slang-ast-iterator.h
+++ b/source/slang/slang-ast-iterator.h
@@ -181,7 +181,7 @@ struct ASTIterator
{
iterator->maybeDispatchCallback(expr);
dispatchIfNotNull(expr->base);
- for (auto candidate : expr->candidiateExprs)
+ for (auto candidate : expr->candidateExprs)
{
dispatchIfNotNull(candidate);
}
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index f70760c5d..d2f338e65 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -354,7 +354,8 @@ DeclRefExpr* SemanticsVisitor::ConstructDeclRefExpr(
// This is the bottleneck for using declarations which might be
// deprecated, diagnose here.
- diagnoseDeprecatedDeclRefUsage(declRef, loc, originalExpr);
+ if (getSink())
+ diagnoseDeprecatedDeclRefUsage(declRef, loc, originalExpr);
// Construct an appropriate expression based on the structured of
// the declaration reference.
@@ -389,7 +390,7 @@ DeclRefExpr* SemanticsVisitor::ConstructDeclRefExpr(
auto expr = m_astBuilder->create<StaticMemberExpr>();
expr->loc = loc;
expr->type = type;
- if (!isDeclUsableAsStaticMember(declRef.getDecl()))
+ if (getSink() && !isDeclUsableAsStaticMember(declRef.getDecl()))
{
getSink()->diagnose(
loc,
@@ -1234,7 +1235,8 @@ Expr* SemanticsVisitor::_resolveOverloadedExprImpl(
DiagnosticSink* diagSink)
{
auto lookupResult = overloadedExpr->lookupResult2;
- SLANG_RELEASE_ASSERT(lookupResult.isValid() && lookupResult.isOverloaded());
+ if (!lookupResult.isValid() || !lookupResult.isOverloaded())
+ return overloadedExpr;
// Take the lookup result we had, and refine it based on what is expected in context.
//
@@ -3827,7 +3829,7 @@ static Expr* _checkHigherOrderInvokeExpr(
auto candidateExpr = actions->createHigherOrderInvokeExpr(semantics);
actions->fillHigherOrderInvokeExpr(candidateExpr, semantics, lookupResultExpr);
candidateExpr->loc = expr->loc;
- result->candidiateExprs.add(candidateExpr);
+ result->candidateExprs.add(candidateExpr);
}
result->type.type = astBuilder->getOverloadedType();
result->loc = expr->loc;
@@ -3836,12 +3838,12 @@ static Expr* _checkHigherOrderInvokeExpr(
else if (auto overloadedExpr2 = as<OverloadedExpr2>(expr->baseFunction))
{
OverloadedExpr2* result = astBuilder->create<OverloadedExpr2>();
- for (auto item : overloadedExpr2->candidiateExprs)
+ for (auto item : overloadedExpr2->candidateExprs)
{
auto candidateExpr = actions->createHigherOrderInvokeExpr(semantics);
actions->fillHigherOrderInvokeExpr(candidateExpr, semantics, item);
candidateExpr->loc = expr->loc;
- result->candidiateExprs.add(candidateExpr);
+ result->candidateExprs.add(candidateExpr);
}
result->type.type = astBuilder->getOverloadedType();
result->loc = expr->loc;
@@ -5181,7 +5183,7 @@ Expr* SemanticsVisitor::_lookupStaticMember(DeclRefExpr* expr, Expr* baseExpress
}
else if (auto overloaded2 = as<OverloadedExpr2>(baseExpression))
{
- for (auto candidate : overloaded2->candidiateExprs)
+ for (auto candidate : overloaded2->candidateExprs)
{
handleLeafExpr(candidate);
}
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp
index 72de3fd61..2c17a6380 100644
--- a/source/slang/slang-check-overload.cpp
+++ b/source/slang/slang-check-overload.cpp
@@ -2492,7 +2492,7 @@ void SemanticsVisitor::AddOverloadCandidates(Expr* funcExpr, OverloadResolveCont
}
else if (auto overloadedExpr2 = as<OverloadedExpr2>(funcExpr))
{
- for (auto item : overloadedExpr2->candidiateExprs)
+ for (auto item : overloadedExpr2->candidateExprs)
{
AddOverloadCandidates(item, context);
}
@@ -3142,7 +3142,7 @@ Expr* SemanticsVisitor::checkGenericAppWithCheckedArgs(GenericAppExpr* genericAp
for (auto candidate : context.bestCandidates)
{
auto candidateExpr = CompleteOverloadCandidate(context, candidate);
- overloadedExpr->candidiateExprs.add(candidateExpr);
+ overloadedExpr->candidateExprs.add(candidateExpr);
}
return overloadedExpr;
}
diff --git a/source/slang/slang-language-server-ast-lookup.cpp b/source/slang/slang-language-server-ast-lookup.cpp
index aa3040f08..cfb8e4d61 100644
--- a/source/slang/slang-language-server-ast-lookup.cpp
+++ b/source/slang/slang-language-server-ast-lookup.cpp
@@ -311,7 +311,7 @@ public:
return true;
bool result = false;
PushNode pushNode(context, expr);
- for (auto candidate : expr->candidiateExprs)
+ for (auto candidate : expr->candidateExprs)
{
result |= dispatchIfNotNull(candidate);
}
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index d65dba71c..aa7f5e495 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -663,7 +663,7 @@ LanguageServerResult<LanguageServerProtocol::Hover> LanguageServerCore::hover(
}
else if (auto overloadedExpr2 = as<OverloadedExpr2>(node))
{
- numOverloads = overloadedExpr2->candidiateExprs.getCount();
+ numOverloads = overloadedExpr2->candidateExprs.getCount();
}
}
if (numOverloads > 1)
@@ -872,9 +872,9 @@ LanguageServerResult<LanguageServerProtocol::Hover> LanguageServerCore::hover(
}
else if (auto overloadedExpr2 = as<OverloadedExpr2>(leafNode))
{
- if (overloadedExpr2->candidiateExprs.getCount() > 0)
+ if (overloadedExpr2->candidateExprs.getCount() > 0)
{
- auto candidateExpr = overloadedExpr2->candidiateExprs[0];
+ auto candidateExpr = overloadedExpr2->candidateExprs[0];
fillExprHoverInfo(candidateExpr);
}
}
@@ -1896,7 +1896,7 @@ LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::
}
else if (auto overloadedExpr2 = as<OverloadedExpr2>(funcExpr))
{
- for (auto item : overloadedExpr2->candidiateExprs)
+ for (auto item : overloadedExpr2->candidateExprs)
{
addExpr(item);
}
diff --git a/source/slang/slang-linkable.cpp b/source/slang/slang-linkable.cpp
index da4cec823..f7dc28171 100644
--- a/source/slang/slang-linkable.cpp
+++ b/source/slang/slang-linkable.cpp
@@ -8,6 +8,7 @@
#include "core/slang-memory-file-system.h"
#include "slang-check-impl.h"
#include "slang-compiler.h"
+#include "slang-lookup.h"
#include "slang-mangle.h"
namespace Slang
@@ -772,6 +773,14 @@ Type* ComponentType::getTypeFromString(String const& typeStr, DiagnosticSink* si
return type;
}
+Expr* ComponentType::tryResolveOverloadedExpr(Expr* exprIn)
+{
+ auto linkage = getLinkage();
+ SemanticsContext context(linkage->getSemanticsForReflection());
+ SemanticsVisitor visitor(context);
+ return visitor.maybeResolveOverloadedExpr(exprIn, LookupMask::Function, nullptr);
+}
+
Expr* ComponentType::findDeclFromString(String const& name, DiagnosticSink* sink)
{
// If we've looked up this type name before,
@@ -905,39 +914,39 @@ Expr* ComponentType::findDeclFromStringInType(
auto checkedTerm = visitor.CheckTerm(expr);
- // Check if checkedTerm is overloaded functions and avoid resolving if so
- // to preserve all function overloads with different signatures
- Expr* resolvedTerm = checkedTerm;
if (auto overloadedExpr = as<OverloadedExpr>(checkedTerm))
{
- // Check if all candidates are function references
- bool allAreFunctions = true;
- for (auto item : overloadedExpr->lookupResult2.items)
+ // For functions, since we don't know the argument list yet, we will have to defer
+ // non-parameter-related candidate comparison logic into its separate step.
+ if (mask != LookupMask::Function)
+ return visitor.maybeResolveOverloadedExpr(checkedTerm, mask, nullptr);
+ overloadedExpr->lookupResult2 = refineLookup(overloadedExpr->lookupResult2, mask);
+
+ // Filter out abstract base interface method implementations for reflection.
+ if (!isInterfaceType(type))
{
- if (!as<FunctionDeclBase>(item.declRef.getDecl()))
+ LookupResult filteredResult;
+ for (auto candidate : overloadedExpr->lookupResult2)
{
- allAreFunctions = false;
- break;
+ if (as<InterfaceDecl>(getParentDecl(candidate.declRef.getDecl())))
+ {
+ if (!candidate.declRef.getDecl()
+ ->hasModifier<HasInterfaceDefaultImplModifier>())
+ continue;
+ }
+ AddToLookupResult(filteredResult, candidate);
}
+ if (filteredResult.isValid() && !filteredResult.isOverloaded())
+ {
+ // If there are exactly one candidate after filtering, we can
+ // safely return resolved expr.
+ return visitor.maybeResolveOverloadedExpr(checkedTerm, mask, nullptr);
+ }
+ overloadedExpr->lookupResult2 = filteredResult;
}
-
- // If not all are functions, resolve the overload as usual
- if (!allAreFunctions)
- {
- resolvedTerm = visitor.maybeResolveOverloadedExpr(checkedTerm, mask, sink);
- }
- }
- else
- {
- // Not overloaded, resolve as usual
- resolvedTerm = visitor.maybeResolveOverloadedExpr(checkedTerm, mask, sink);
- }
-
- if (auto overloadedExpr = as<OverloadedExpr>(resolvedTerm))
- {
return overloadedExpr;
}
- if (auto declRefExpr = as<DeclRefExpr>(resolvedTerm))
+ if (auto declRefExpr = as<DeclRefExpr>(checkedTerm))
{
return declRefExpr;
}
diff --git a/source/slang/slang-linkable.h b/source/slang/slang-linkable.h
index e900fd275..04a5c3c88 100644
--- a/source/slang/slang-linkable.h
+++ b/source/slang/slang-linkable.h
@@ -264,6 +264,7 @@ public:
Type* getTypeFromString(String const& typeStr, DiagnosticSink* sink);
Expr* findDeclFromString(String const& name, DiagnosticSink* sink);
+ Expr* tryResolveOverloadedExpr(Expr* exprIn);
Expr* findDeclFromStringInType(
Type* type,
diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp
index 56a82e17e..95dcc6249 100644
--- a/source/slang/slang-reflection-api.cpp
+++ b/source/slang/slang-reflection-api.cpp
@@ -5,6 +5,7 @@
#include "slang-check.h"
#include "slang-compiler.h"
#include "slang-deprecated.h"
+#include "slang-lookup.h"
#include "slang-syntax.h"
#include "slang-type-layout.h"
#include "slang.h"
@@ -994,6 +995,45 @@ SLANG_API SlangReflectionFunction* spReflection_FindFunctionByNameInType(
return nullptr;
}
+
+SLANG_API SlangReflectionFunction* spReflection_TryResolveOverloadedFunction(
+ SlangReflection* reflection,
+ uint32_t candidateCount,
+ SlangReflectionFunction** candidates)
+{
+ auto programLayout = convert(reflection);
+ auto program = programLayout->getProgram();
+ auto astBuilder = program->getLinkage()->getASTBuilder();
+ SLANG_AST_BUILDER_RAII(astBuilder);
+ OverloadedExpr* overloadedFunc = nullptr;
+ if (candidateCount == 1)
+ {
+ overloadedFunc = convertToOverloadedFunc(candidates[0]);
+ if (!overloadedFunc)
+ return candidates[0];
+ }
+ else
+ {
+ overloadedFunc = astBuilder->create<OverloadedExpr>();
+ overloadedFunc->type = astBuilder->getOrCreate<OverloadGroupType>();
+ for (uint32_t i = 0; i < candidateCount; i++)
+ {
+ auto func = convertToFunc(candidates[i]);
+ AddToLookupResult(overloadedFunc->lookupResult2, LookupResultItem(func));
+ }
+ }
+
+ try
+ {
+ auto result = program->tryResolveOverloadedExpr(overloadedFunc);
+ return tryConvertExprToFunctionReflection(astBuilder, result);
+ }
+ catch (...)
+ {
+ }
+ return nullptr;
+}
+
SLANG_API SlangReflectionVariable* spReflection_FindVarByNameInType(
SlangReflection* reflection,
SlangReflectionType* reflType,