Skip to content

Commit 2f44f5b

Browse files
committed
[ConstraintSystem] Extract logic that identifies application based on its argument node
1 parent 34b532a commit 2f44f5b

File tree

2 files changed

+68
-40
lines changed

2 files changed

+68
-40
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4994,6 +4994,13 @@ class ConstraintSystem {
49944994
/// diagnostic.
49954995
void maybeProduceFallbackDiagnostic(SolutionApplicationTarget target) const;
49964996

4997+
/// Check whether given AST node represents an argument of an application
4998+
/// of some sort (call, operator invocation, subscript etc.)
4999+
/// and return AST node representing and argument index. E.g. for regular
5000+
/// calls `test(42)` passing `42` should return node representing
5001+
/// entire call and index `0`.
5002+
Optional<std::pair<Expr *, unsigned>> isArgumentExpr(Expr *expr);
5003+
49975004
SWIFT_DEBUG_DUMP;
49985005
SWIFT_DEBUG_DUMPER(dump(Expr *));
49995006

lib/Sema/ConstraintSystem.cpp

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,12 +3770,14 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
37703770
const auto &solution = *entry.first;
37713771
const auto *fix = entry.second;
37723772

3773-
if (fix->getLocator()->isForContextualType()) {
3773+
auto *locator = fix->getLocator();
3774+
3775+
if (locator->isForContextualType()) {
37743776
contextualFixes.push_back({&solution, fix});
37753777
continue;
37763778
}
37773779

3778-
auto *calleeLocator = solution.getCalleeLocator(fix->getLocator());
3780+
auto *calleeLocator = solution.getCalleeLocator(locator);
37793781
fixesByCallee[calleeLocator].push_back({&solution, fix});
37803782
}
37813783

@@ -4533,46 +4535,13 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
45334535
// It's only valid to use `&` in argument positions, but we need
45344536
// to figure out exactly where it was used.
45354537
if (auto *argExpr = getAsExpr<InOutExpr>(locator->getAnchor())) {
4536-
auto *argList = cs.getParentExpr(argExpr);
4537-
assert(argList);
4538-
4539-
// `inout` expression might be wrapped in a number of
4540-
// parens e.g. `test(((&x)))`.
4541-
if (isa<ParenExpr>(argList)) {
4542-
for (;;) {
4543-
auto nextParent = cs.getParentExpr(argList);
4544-
assert(nextParent && "Incorrect use of `inout` expression");
4545-
4546-
// e.g. `test((&x), x: ...)`
4547-
if (isa<TupleExpr>(nextParent)) {
4548-
argList = nextParent;
4549-
break;
4550-
}
4551-
4552-
// e.g. `test(((&x)))`
4553-
if (isa<ParenExpr>(nextParent)) {
4554-
argList = nextParent;
4555-
continue;
4556-
}
4557-
4558-
break;
4559-
}
4560-
}
4538+
auto argInfo = cs.isArgumentExpr(argExpr);
4539+
assert(argInfo && "Incorrect use of `inout` expression");
45614540

4562-
unsigned argIdx = 0;
4563-
if (auto *tuple = dyn_cast<TupleExpr>(argList)) {
4564-
auto arguments = tuple->getElements();
4541+
Expr *call;
4542+
unsigned argIdx;
45654543

4566-
for (auto idx : indices(arguments)) {
4567-
if (arguments[idx]->getSemanticsProvidingExpr() == argExpr) {
4568-
argIdx = idx;
4569-
break;
4570-
}
4571-
}
4572-
}
4573-
4574-
auto *call = cs.getParentExpr(argList);
4575-
assert(call);
4544+
std::tie(call, argIdx) = *argInfo;
45764545

45774546
ParameterTypeFlags flags;
45784547
locator = cs.getConstraintLocator(
@@ -4746,6 +4715,58 @@ bool constraints::isStandardComparisonOperator(ASTNode node) {
47464715
return false;
47474716
}
47484717

4718+
Optional<std::pair<Expr *, unsigned>>
4719+
ConstraintSystem::isArgumentExpr(Expr *expr) {
4720+
auto *argList = getParentExpr(expr);
4721+
4722+
if (isa<ParenExpr>(argList)) {
4723+
for (;;) {
4724+
auto *parent = getParentExpr(argList);
4725+
if (!parent)
4726+
return None;
4727+
4728+
if (isa<TupleExpr>(parent)) {
4729+
argList = parent;
4730+
break;
4731+
}
4732+
4733+
// Drop all of the semantically insignificant parens
4734+
// that might be wrapping an argument e.g. `test(((42)))`
4735+
if (isa<ParenExpr>(parent)) {
4736+
argList = parent;
4737+
continue;
4738+
}
4739+
4740+
break;
4741+
}
4742+
}
4743+
4744+
if (!(isa<ParenExpr>(argList) || isa<TupleExpr>(argList)))
4745+
return None;
4746+
4747+
auto *application = getParentExpr(argList);
4748+
if (!application)
4749+
return None;
4750+
4751+
if (!(isa<ApplyExpr>(application) || isa<SubscriptExpr>(application) ||
4752+
isa<ObjectLiteralExpr>(application)))
4753+
return None;
4754+
4755+
unsigned argIdx = 0;
4756+
if (auto *tuple = dyn_cast<TupleExpr>(argList)) {
4757+
auto arguments = tuple->getElements();
4758+
4759+
for (auto idx : indices(arguments)) {
4760+
if (arguments[idx]->getSemanticsProvidingExpr() == expr) {
4761+
argIdx = idx;
4762+
break;
4763+
}
4764+
}
4765+
}
4766+
4767+
return std::make_pair(application, argIdx);
4768+
}
4769+
47494770
bool constraints::isOperatorArgument(ConstraintLocator *locator,
47504771
StringRef expectedOperator) {
47514772
if (!locator->findLast<LocatorPathElt::ApplyArgToParam>())

0 commit comments

Comments
 (0)