Skip to content

Commit 43ca7df

Browse files
committed
[CSOptimizer] Simplify handling of non-applied disjunctions
If a disjunction doesn't have an application, let's prefer it if it's passed as an argument to an operator application or involved in a member chain, in such situations attempting a disjunction could provide context to parent call/member chain. If disjunction is passed as an unapplied reference to some parameter i.e. `<base>.map(String.init(describing:))` we don't favor it for now because optimizer cannot do enough checking to determine whether preferring such disjunction would help make forward progress in solving by pruning some space or providing additional context.
1 parent f7d81d5 commit 43ca7df

File tree

2 files changed

+37
-36
lines changed

2 files changed

+37
-36
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -253,37 +253,6 @@ static void findFavoredChoicesBasedOnArity(
253253
favoredChoice(choice);
254254
}
255255

256-
/// Determine whether the given disjunction serves as a base of
257-
/// another member reference i.e. `x.y` where `x` could be overloaded.
258-
static bool isPartOfMemberChain(ConstraintSystem &CS, Constraint *disjunction) {
259-
if (isOperatorDisjunction(disjunction))
260-
return false;
261-
262-
auto &CG = CS.getConstraintGraph();
263-
264-
TypeVariableType *typeVar = nullptr;
265-
266-
// If disjunction is applied, the member is chained on the result.
267-
if (auto appliedFn = CS.getAppliedDisjunctionArgumentFunction(disjunction)) {
268-
typeVar = appliedFn->getResult()->getAs<TypeVariableType>();
269-
} else {
270-
typeVar = disjunction->getNestedConstraints()[0]
271-
->getFirstType()
272-
->getAs<TypeVariableType>();
273-
}
274-
275-
if (!typeVar)
276-
return false;
277-
278-
return llvm::any_of(
279-
CG[typeVar].getConstraints(), [&typeVar](Constraint *constraint) {
280-
if (constraint->getKind() != ConstraintKind::ValueMember)
281-
return false;
282-
283-
return constraint->getFirstType()->isEqual(typeVar);
284-
});
285-
}
286-
287256
} // end anonymous namespace
288257

289258
/// Given a set of disjunctions, attempt to determine
@@ -318,11 +287,26 @@ static void determineBestChoicesInContext(
318287
getApplicableFnConstraint(cs.getConstraintGraph(), disjunction);
319288

320289
if (applicableFn.isNull()) {
321-
// If this is a chained member reference it could be prioritized since
322-
// it helps to establish context for other calls i.e. `a.b + 2` if
323-
// `a` is a disjunction it should be preferred over `+`.
324-
if (isPartOfMemberChain(cs, disjunction))
325-
recordResult(disjunction, {/*score=*/1.0});
290+
auto *locator = disjunction->getLocator();
291+
if (auto expr = getAsExpr(locator->getAnchor())) {
292+
if (auto *parentExpr = cs.getParentExpr(expr)) {
293+
// If this is a chained member reference or a direct operator
294+
// argument it could be prioritized since it helps to establish
295+
// context for other calls i.e. `(a.)b + 2` if `a` and/or `b`
296+
// are disjunctions they should be preferred over `+`.
297+
switch (parentExpr->getKind()) {
298+
case ExprKind::Binary:
299+
case ExprKind::PrefixUnary:
300+
case ExprKind::PostfixUnary:
301+
case ExprKind::UnresolvedDot:
302+
recordResult(disjunction, {/*score=*/1.0});
303+
continue;
304+
305+
default:
306+
break;
307+
}
308+
}
309+
}
326310

327311
continue;
328312
}

test/Constraints/operator.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,3 +375,20 @@ do {
375375
col <<<>>> val // Ok
376376
}
377377
}
378+
379+
// Make sure that ?? selects an overload that doesn't produce an optional.
380+
do {
381+
class Obj {
382+
var x: String!
383+
}
384+
385+
class Child : Obj {
386+
func x() -> String? { nil }
387+
static func x(_: Int) -> String { "" }
388+
}
389+
390+
func test(arr: [Child], v: String, defaultV: Child) -> Child {
391+
let result = arr.first { $0.x == v } ?? defaultV
392+
return result // Ok
393+
}
394+
}

0 commit comments

Comments
 (0)