summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-conversion.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-08-07 08:10:02 -0700
committerGitHub <noreply@github.com>2025-08-07 15:10:02 +0000
commit7cd8130e1a3dbcca8746e0577fb8df3bf2975bf8 (patch)
tree6da2b411da34039c3d0ec0e06fadd0e13f8f4842 /source/slang/slang-check-conversion.cpp
parent67a96920674d628f615532a302504544a45e8187 (diff)
Support `expand` on concrete tuple values. (#8106)
Closes #8061. Along with the fix, also enhanced coercion/overload resolution to filter candidates based on the target type, allowing `tests\language-feature\higher-order-functions\overloaded.slang` to pass.
Diffstat (limited to 'source/slang/slang-check-conversion.cpp')
-rw-r--r--source/slang/slang-check-conversion.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index a605928e3..758c23a5f 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -1191,10 +1191,10 @@ bool SemanticsVisitor::_coerce(
// then we should start by trying to resolve the ambiguous reference
// based on prioritization of the different candidates.
//
- // TODO: A more powerful model would be to try to coerce each
+ // If `fromExpr` is overloaded, we will try to coerce each
// of the constituent overload candidates, filtering down to
// those that are coercible, and then disambiguating the result.
- // Such an approach would let us disambiguate between overloaded
+ // Such an approach lets us disambiguate between overloaded
// symbols based on their type (e.g., by casting the name of
// an overloaded function to the type of the overload we mean
// to reference).
@@ -1202,11 +1202,49 @@ bool SemanticsVisitor::_coerce(
if (auto fromOverloadedExpr = as<OverloadedExpr>(fromExpr))
{
auto resolvedExpr =
- maybeResolveOverloadedExpr(fromOverloadedExpr, LookupMask::Default, nullptr);
+ maybeResolveOverloadedExpr(fromOverloadedExpr, LookupMask::Default, toType, nullptr);
fromExpr = resolvedExpr;
fromType = resolvedExpr->type;
}
+ else if (auto overloadedExpr2 = as<OverloadedExpr2>(fromExpr))
+ {
+ ShortList<Expr*> coercibleCandidates;
+ for (auto candidate : overloadedExpr2->candidateExprs)
+ {
+ if (canCoerce(toType, candidate->type, candidate))
+ coercibleCandidates.add(candidate);
+ }
+ if (coercibleCandidates.getCount() == 1)
+ {
+ return _coerce(
+ site,
+ toType,
+ outToExpr,
+ coercibleCandidates[0]->type,
+ coercibleCandidates[0],
+ sink,
+ outCost);
+ }
+ if (sink)
+ {
+ auto firstCandidate = overloadedExpr2->candidateExprs.getCount() > 0
+ ? overloadedExpr2->candidateExprs[0]
+ : nullptr;
+ if (auto declCandidate = as<DeclRefExpr>(firstCandidate))
+ {
+ sink->diagnose(
+ fromExpr->loc,
+ Diagnostics::ambiguousReference,
+ declCandidate->declRef);
+ }
+ else
+ {
+ sink->diagnose(fromExpr->loc, Diagnostics::ambiguousExpression);
+ }
+ }
+ return false;
+ }
// An important and easy case is when the "to" and "from" types are equal.
//