Skip to content

Commit 5824db9

Browse files
authored
Merge pull request #11855 from xedin/disallow-subtype-contractions
[ConstraintGraph] Disallow subtype constraint contractions
2 parents d6fb3c5 + 0a178fd commit 5824db9

File tree

2 files changed

+43
-21
lines changed

2 files changed

+43
-21
lines changed

lib/Sema/ConstraintGraph.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -641,13 +641,6 @@ static bool shouldContractEdge(ConstraintKind kind) {
641641
case ConstraintKind::BindParam:
642642
case ConstraintKind::BindToPointerType:
643643
case ConstraintKind::Equal:
644-
645-
// We currently only allow subtype contractions for the purpose of
646-
// parameter binding constraints.
647-
// TODO: We do this because of how inout parameter bindings are handled
648-
// for implicit closure parameters. We should consider adjusting our
649-
// current approach to unlock more opportunities for subtype contractions.
650-
case ConstraintKind::Subtype:
651644
return true;
652645

653646
default:
@@ -671,12 +664,7 @@ static bool isStrictInoutSubtypeConstraint(Constraint *constraint) {
671664
t1 = tt->getElementType(0).getPointer();
672665
}
673666

674-
auto iot = t1->getAs<InOutType>();
675-
676-
if (!iot)
677-
return false;
678-
679-
return !iot->getObjectType()->isTypeVariableOrMember();
667+
return t1->is<InOutType>();
680668
}
681669

682670
bool ConstraintGraph::contractEdges() {
@@ -698,14 +686,6 @@ bool ConstraintGraph::contractEdges() {
698686
auto t1 = constraint->getFirstType()->getDesugaredType();
699687
auto t2 = constraint->getSecondType()->getDesugaredType();
700688

701-
if (kind == ConstraintKind::Subtype) {
702-
if (auto iot1 = t1->getAs<InOutType>()) {
703-
t1 = iot1->getObjectType().getPointer();
704-
} else {
705-
continue;
706-
}
707-
}
708-
709689
auto tyvar1 = t1->getAs<TypeVariableType>();
710690
auto tyvar2 = t2->getAs<TypeVariableType>();
711691

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
4+
class C {
5+
var a: Int = 0
6+
var b: Int = 0
7+
}
8+
9+
@inline(never)
10+
func foo<T>(_ item: T, update: (inout T) throws -> Void) rethrows -> T {
11+
var this = item
12+
try update(&this)
13+
return this
14+
}
15+
16+
// Test single statement closure because it's type-checked
17+
// together with the call to `foo`
18+
19+
let rdar34333874_1 = foo(C()) {
20+
$0.a = 42
21+
}
22+
23+
// The multi-statement closure which is type-checked
24+
// separately from call to `foo`
25+
26+
let rdar34333874_2 = foo(C()) {
27+
$0.a = 42
28+
$0.b = 0
29+
}
30+
31+
print(rdar34333874_1)
32+
print(rdar34333874_2)
33+
34+
// Example which avoids mutating fields of the class
35+
36+
@inline(never)
37+
func bar(_ o : C) {
38+
let _ = foo(o) { (item) in
39+
}
40+
}
41+
42+
bar(C())

0 commit comments

Comments
 (0)