@@ -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+
47494770bool constraints::isOperatorArgument (ConstraintLocator *locator,
47504771 StringRef expectedOperator) {
47514772 if (!locator->findLast <LocatorPathElt::ApplyArgToParam>())
0 commit comments