@@ -3770,12 +3770,14 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
3770
3770
const auto &solution = *entry.first ;
3771
3771
const auto *fix = entry.second ;
3772
3772
3773
- if (fix->getLocator ()->isForContextualType ()) {
3773
+ auto *locator = fix->getLocator ();
3774
+
3775
+ if (locator->isForContextualType ()) {
3774
3776
contextualFixes.push_back ({&solution, fix});
3775
3777
continue ;
3776
3778
}
3777
3779
3778
- auto *calleeLocator = solution.getCalleeLocator (fix-> getLocator () );
3780
+ auto *calleeLocator = solution.getCalleeLocator (locator );
3779
3781
fixesByCallee[calleeLocator].push_back ({&solution, fix});
3780
3782
}
3781
3783
@@ -4533,46 +4535,13 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
4533
4535
// It's only valid to use `&` in argument positions, but we need
4534
4536
// to figure out exactly where it was used.
4535
4537
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" );
4561
4540
4562
- unsigned argIdx = 0 ;
4563
- if (auto *tuple = dyn_cast<TupleExpr>(argList)) {
4564
- auto arguments = tuple->getElements ();
4541
+ Expr *call;
4542
+ unsigned argIdx;
4565
4543
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;
4576
4545
4577
4546
ParameterTypeFlags flags;
4578
4547
locator = cs.getConstraintLocator (
@@ -4746,6 +4715,58 @@ bool constraints::isStandardComparisonOperator(ASTNode node) {
4746
4715
return false ;
4747
4716
}
4748
4717
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
+
4749
4770
bool constraints::isOperatorArgument (ConstraintLocator *locator,
4750
4771
StringRef expectedOperator) {
4751
4772
if (!locator->findLast <LocatorPathElt::ApplyArgToParam>())
0 commit comments