Skip to content

Commit cff64ec

Browse files
authored
Merge pull request #14318 from xedin/rdar-36838495-5.0
2 parents f43883e + da5d588 commit cff64ec

File tree

3 files changed

+73
-10
lines changed

3 files changed

+73
-10
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,9 +1788,10 @@ static bool shouldSkipDisjunctionChoice(ConstraintSystem &cs,
17881788
// Let's skip generic overload choices only in case if
17891789
// non-generic score indicates that there were no forced
17901790
// unwrappings of optional(s), no unavailable overload
1791-
// choices present in the solution, and no fixes required.
1792-
if (score[SK_ForceUnchecked] == 0 && score[SK_Unavailable] == 0
1793-
&& score[SK_Fix] == 0)
1791+
// choices present in the solution, no fixes required,
1792+
// and there are no non-trivial function conversions.
1793+
if (score[SK_ForceUnchecked] == 0 && score[SK_Unavailable] == 0 &&
1794+
score[SK_Fix] == 0 && score[SK_FunctionConversion] == 0)
17941795
return true;
17951796
}
17961797

lib/Sema/ConstraintGraph.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -675,13 +675,39 @@ bool ConstraintGraph::contractEdges() {
675675

676676
auto isParamBindingConstraint = kind == ConstraintKind::BindParam;
677677

678-
// If the parameter is allowed to bind to `inout` let's not
679-
// try to contract the edge connecting parameter declaration to
680-
// it's use in the body. If parameter declaration is bound to
681-
// `inout` it's use has to be bound to `l-value`, which can't
682-
// happen once equivalence classes of parameter and argument are merged.
683-
if (isParamBindingConstraint && tyvar1->getImpl().canBindToInOut())
684-
continue;
678+
// If the argument is allowed to bind to `inout`, in general,
679+
// it's invalid to contract the edge between argument and parameter,
680+
// but if we can prove that there are no possible bindings
681+
// which result in attempt to bind `inout` type to argument
682+
// type variable, we should go ahead and allow (temporary)
683+
// contraction, because that greatly helps with performance.
684+
// Such action is valid because argument type variable can
685+
// only get its bindings from related overload, which gives
686+
// us enough information to decided on l-valueness.
687+
if (isParamBindingConstraint && tyvar1->getImpl().canBindToInOut()) {
688+
bool isNotContractable = true;
689+
if (auto bindings = CS.getPotentialBindings(tyvar1)) {
690+
for (auto &binding : bindings.Bindings) {
691+
auto type = binding.BindingType;
692+
isNotContractable = type.findIf([&](Type nestedType) -> bool {
693+
if (auto tv = nestedType->getAs<TypeVariableType>()) {
694+
if (!tv->getImpl().mustBeMaterializable())
695+
return true;
696+
}
697+
698+
return nestedType->is<InOutType>();
699+
});
700+
701+
// If there is at least one non-contractable binding, let's
702+
// not risk contracting this edge.
703+
if (isNotContractable)
704+
break;
705+
}
706+
}
707+
708+
if (isNotContractable)
709+
continue;
710+
}
685711

686712
auto rep1 = CS.getRepresentative(tyvar1);
687713
auto rep2 = CS.getRepresentative(tyvar2);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
2+
// REQUIRES: tools-release,no_asserts
3+
4+
struct T {
5+
enum B {
6+
case a
7+
case b
8+
}
9+
10+
let name: String
11+
let b: B
12+
}
13+
14+
struct A {
15+
enum C {
16+
case a
17+
case b
18+
case c
19+
}
20+
21+
let name: String
22+
let t: T
23+
let c: C
24+
25+
var isX: Bool {
26+
return self.t.b == .a
27+
}
28+
}
29+
30+
let x: [String: A] = [:]
31+
let _ = x.values.filter { $0.isX }
32+
.filter { $0.t.b != .a }
33+
.filter { $0.c == .a || $0.c == .b }
34+
.filter { $0.isX }
35+
.filter { $0.t.b != .a }
36+
.sorted { $0.name < $1.name }

0 commit comments

Comments
 (0)