Skip to content

Commit 34b985b

Browse files
authored
Merge pull request #20524 from xedin/5.0-rdar-45659733
[5.0][CSBindings] Detect situations when type variable bindings could be i…
2 parents aed5486 + 080188a commit 34b985b

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,20 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
423423
case ConstraintKind::ArgumentConversion:
424424
case ConstraintKind::OperatorArgumentConversion:
425425
case ConstraintKind::OptionalObject: {
426+
// If there is a `bind param` constraint associated with
427+
// current type variable, result should be aware of that
428+
// fact. Binding set might be incomplete until
429+
// this constraint is resolved, because we currently don't
430+
// look-through constraints expect to `subtype` to try and
431+
// find related bindings.
432+
// This only affects type variable that appears one the
433+
// right-hand side of the `bind param` constraint and
434+
// represents result type of the closure body, because
435+
// left-hand side gets types from overload choices.
436+
if (constraint->getKind() == ConstraintKind::BindParam &&
437+
constraint->getSecondType()->isEqual(typeVar))
438+
result.PotentiallyIncomplete = true;
439+
426440
auto binding = getPotentialBindingForRelationalConstraint(
427441
result, constraint, hasDependentMemberRelationalConstraints,
428442
hasNonDependentMemberRelationalConstraints,

lib/Sema/ConstraintSystem.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2807,6 +2807,12 @@ class ConstraintSystem {
28072807
/// Whether the bindings of this type involve other type variables.
28082808
bool InvolvesTypeVariables = false;
28092809

2810+
/// Whether the bindings represent (potentially) incomplete set,
2811+
/// there is no way to say with absolute certainty if that's the
2812+
/// case, but that could happen when certain constraints like
2813+
/// `bind param` are present in the system.
2814+
bool PotentiallyIncomplete = false;
2815+
28102816
/// Whether this type variable has literal bindings.
28112817
LiteralBindingKind LiteralBinding = LiteralBindingKind::None;
28122818

@@ -2851,9 +2857,14 @@ class ConstraintSystem {
28512857
if (formBindingScore(y) < formBindingScore(x))
28522858
return false;
28532859

2854-
// If the only difference is default types,
2860+
// If there is a difference in number of default types,
28552861
// prioritize bindings with fewer of them.
2856-
return x.NumDefaultableBindings < y.NumDefaultableBindings;
2862+
if (x.NumDefaultableBindings != y.NumDefaultableBindings)
2863+
return x.NumDefaultableBindings < y.NumDefaultableBindings;
2864+
2865+
// As a last resort, let's check if the bindings are
2866+
// potentially incomplete, and if so, let's de-prioritize them.
2867+
return x.PotentiallyIncomplete < y.PotentiallyIncomplete;
28572868
}
28582869

28592870
void foundLiteralBinding(ProtocolDecl *proto) {
@@ -2886,6 +2897,8 @@ class ConstraintSystem {
28862897
void dump(llvm::raw_ostream &out,
28872898
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
28882899
out.indent(indent);
2900+
if (PotentiallyIncomplete)
2901+
out << "potentially_incomplete ";
28892902
if (FullyBound)
28902903
out << "fully_bound ";
28912904
if (SubtypeOfExistentialType)

test/Constraints/closures.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,31 @@ func test<Instances : Collection>(
797797
) { fatalError() }
798798

799799
test([1]) { _, _ in fatalError(); () }
800+
801+
// rdar://problem/45659733
802+
func rdar_45659733() {
803+
func foo<T : BinaryInteger>(_: AnyHashable, _: T) {}
804+
func bar(_ a: Int, _ b: Int) {
805+
_ = (a ..< b).map { i in foo(i, i) } // Ok
806+
}
807+
808+
struct S<V> {
809+
func map<T>(
810+
get: @escaping (V) -> T,
811+
set: @escaping (inout V, T) -> Void
812+
) -> S<T> {
813+
fatalError()
814+
}
815+
816+
subscript<T>(
817+
keyPath: WritableKeyPath<V, T?>,
818+
default defaultValue: T
819+
) -> S<T> {
820+
return map(
821+
get: { $0[keyPath: keyPath] ?? defaultValue },
822+
set: { $0[keyPath: keyPath] = $1 }
823+
) // Ok, make sure that we deduce result to be S<T>
824+
}
825+
}
826+
}
827+

0 commit comments

Comments
 (0)