diff options
| author | Yong He <yonghe@outlook.com> | 2025-08-07 08:10:02 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-07 15:10:02 +0000 |
| commit | 7cd8130e1a3dbcca8746e0577fb8df3bf2975bf8 (patch) | |
| tree | 6da2b411da34039c3d0ec0e06fadd0e13f8f4842 /source/slang/slang-check-conversion.cpp | |
| parent | 67a96920674d628f615532a302504544a45e8187 (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.cpp | 44 |
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. // |
