Skip to content

Commit 65e338e

Browse files
committed
[Constraint solver] Do not allow unavailable decls to be favored.
There is a short-circuiting hack in the constraint solver that speeds up solving, but isn't generally sound. If we allow unavailable decls to be considered "favored", this can fire and result in our choosing a solution that involves the unavailable decl where other solutions exist. Fixes rdar://problem/32570734.
1 parent 75dcb28 commit 65e338e

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2980,8 +2980,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
29802980
}
29812981
}
29822982
}
2983-
2984-
// If the invocation's argument expression has a favored constraint,
2983+
2984+
// If the invocation's argument expression has a favored type,
29852985
// use that information to determine whether a specific overload for
29862986
// the initializer should be favored.
29872987
if (favoredType && result.FavoredChoice == ~0U) {
@@ -2996,7 +2996,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
29962996
argType = ctor.Decl->getInnermostDeclContext()
29972997
->mapTypeIntoContext(argType);
29982998
if (argType->isEqual(favoredType))
2999-
result.FavoredChoice = result.ViableCandidates.size();
2999+
if (!ctor->getAttrs().isUnavailable(getASTContext()))
3000+
result.FavoredChoice = result.ViableCandidates.size();
30003001
}
30013002
}
30023003
}

lib/Sema/CSSolver.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,11 +2338,21 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
23382338
/// Whether we should short-circuit a disjunction that already has a
23392339
/// solution when we encounter the given constraint.
23402340
static bool shortCircuitDisjunctionAt(Constraint *constraint,
2341-
Constraint *successfulConstraint) {
2342-
2341+
Constraint *successfulConstraint,
2342+
ASTContext &ctx) {
2343+
23432344
// If the successfully applied constraint is favored, we'll consider that to
23442345
// be the "best".
23452346
if (successfulConstraint->isFavored() && !constraint->isFavored()) {
2347+
#if !defined(NDEBUG)
2348+
if (successfulConstraint->getKind() == ConstraintKind::BindOverload) {
2349+
auto overloadChoice = successfulConstraint->getOverloadChoice();
2350+
assert((!overloadChoice.isDecl() ||
2351+
!overloadChoice.getDecl()->getAttrs().isUnavailable(ctx)) &&
2352+
"Unavailable decl should not be favored!");
2353+
}
2354+
#endif
2355+
23462356
return true;
23472357
}
23482358

@@ -2533,7 +2543,8 @@ bool ConstraintSystem::solveSimplified(
25332543
// short-circuit the disjunction.
25342544
if (lastSolvedChoice) {
25352545
auto *lastChoice = lastSolvedChoice->getConstraint();
2536-
if (shortCircuitDisjunctionAt(&currentChoice, lastChoice))
2546+
if (shortCircuitDisjunctionAt(&currentChoice, lastChoice,
2547+
getASTContext()))
25372548
break;
25382549
}
25392550

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,11 @@ void ConstraintSystem::addOverloadSet(Type boundType,
13141314
*favoredChoice,
13151315
useDC,
13161316
locator);
1317-
1317+
1318+
assert((!favoredChoice->isDecl() ||
1319+
!favoredChoice->getDecl()->getAttrs().isUnavailable(
1320+
getASTContext())) &&
1321+
"Cannot make unavailable decl favored!");
13181322
bindOverloadConstraint->setFavored();
13191323

13201324
overloads.push_back(bindOverloadConstraint);

test/Constraints/availability.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 4
2+
3+
// Ensure that we do not select the unavailable failable init as the
4+
// only solution and then fail to typecheck.
5+
protocol P {}
6+
7+
class C : P {
8+
@available(swift, obsoleted: 4)
9+
public init?(_ c: C) {
10+
}
11+
12+
public init<T : P>(_ c: T) {}
13+
}
14+
15+
func f(c: C) {
16+
let _: C? = C(c)
17+
}

0 commit comments

Comments
 (0)