Skip to content

Commit 17ea39a

Browse files
committed
[Constraint solver] Simplify one-way constraints to Equal, not Bind.
One-way constraint expressions, which are the only things that introduce one-way constraints at this point, want to look through lvalue types to produce values. Rename OneWayBind to OneWayEqual, map it down to an Equal constraint when it is simplified (to drop lvalue-ness), and apply that coercion during constraint application. Part of rdar://problem/50150793.
1 parent da267bf commit 17ea39a

File tree

10 files changed

+43
-36
lines changed

10 files changed

+43
-36
lines changed

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4635,7 +4635,8 @@ namespace {
46354635
}
46364636

46374637
Expr *visitOneWayExpr(OneWayExpr *E) {
4638-
return E->getSubExpr();
4638+
auto type = simplifyType(cs.getType(E));
4639+
return coerceToType(E->getSubExpr(), type, cs.getConstraintLocator(E));
46394640
}
46404641

46414642
Expr *visitTapExpr(TapExpr *E) {

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
633633
}
634634
break;
635635

636-
case ConstraintKind::OneWayBind: {
636+
case ConstraintKind::OneWayEqual: {
637637
// Don't produce any bindings if this type variable is on the left-hand
638638
// side of a one-way binding.
639639
auto firstType = constraint->getFirstType();

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3083,7 +3083,7 @@ namespace {
30833083
Type visitOneWayExpr(OneWayExpr *expr) {
30843084
auto locator = CS.getConstraintLocator(expr);
30853085
auto resultTypeVar = CS.createTypeVariable(locator, 0);
3086-
CS.addConstraint(ConstraintKind::OneWayBind, resultTypeVar,
3086+
CS.addConstraint(ConstraintKind::OneWayEqual, resultTypeVar,
30873087
CS.getType(expr->getSubExpr()), locator);
30883088
return resultTypeVar;
30893089
}

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
11461146
case ConstraintKind::BridgingConversion:
11471147
case ConstraintKind::FunctionInput:
11481148
case ConstraintKind::FunctionResult:
1149-
case ConstraintKind::OneWayBind:
1149+
case ConstraintKind::OneWayEqual:
11501150
llvm_unreachable("Not a conversion");
11511151
}
11521152

@@ -1209,7 +1209,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
12091209
case ConstraintKind::ValueMember:
12101210
case ConstraintKind::FunctionInput:
12111211
case ConstraintKind::FunctionResult:
1212-
case ConstraintKind::OneWayBind:
1212+
case ConstraintKind::OneWayEqual:
12131213
return false;
12141214
}
12151215

@@ -1394,7 +1394,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
13941394
case ConstraintKind::BridgingConversion:
13951395
case ConstraintKind::FunctionInput:
13961396
case ConstraintKind::FunctionResult:
1397-
case ConstraintKind::OneWayBind:
1397+
case ConstraintKind::OneWayEqual:
13981398
llvm_unreachable("Not a relational constraint");
13991399
}
14001400

@@ -2811,7 +2811,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
28112811
case ConstraintKind::ValueMember:
28122812
case ConstraintKind::FunctionInput:
28132813
case ConstraintKind::FunctionResult:
2814-
case ConstraintKind::OneWayBind:
2814+
case ConstraintKind::OneWayEqual:
28152815
llvm_unreachable("Not a relational constraint");
28162816
}
28172817
}
@@ -5248,7 +5248,7 @@ ConstraintSystem::simplifyOneWayConstraint(
52485248
}
52495249

52505250
// Translate this constraint into a one-way binding constraint.
5251-
return matchTypes(first, secondSimplified, ConstraintKind::Bind, flags,
5251+
return matchTypes(first, secondSimplified, ConstraintKind::Equal, flags,
52525252
locator);
52535253
}
52545254

@@ -7296,7 +7296,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
72967296
return simplifyFunctionComponentConstraint(kind, first, second,
72977297
subflags, locator);
72987298

7299-
case ConstraintKind::OneWayBind:
7299+
case ConstraintKind::OneWayEqual:
73007300
return simplifyOneWayConstraint(kind, first, second, subflags, locator);
73017301

73027302
case ConstraintKind::ValueMember:
@@ -7655,7 +7655,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
76557655
// Disjunction constraints are never solved here.
76567656
return SolutionKind::Unsolved;
76577657

7658-
case ConstraintKind::OneWayBind:
7658+
case ConstraintKind::OneWayEqual:
76597659
return simplifyOneWayConstraint(constraint.getKind(),
76607660
constraint.getFirstType(),
76617661
constraint.getSecondType(),

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1681,7 +1681,7 @@ void ConstraintSystem::ArgumentInfoCollector::walk(Type argType) {
16811681
case ConstraintKind::SelfObjectOfProtocol:
16821682
case ConstraintKind::ConformsTo:
16831683
case ConstraintKind::Defaultable:
1684-
case ConstraintKind::OneWayBind:
1684+
case ConstraintKind::OneWayEqual:
16851685
break;
16861686
}
16871687
}

lib/Sema/CSStep.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ StepResult ComponentStep::take(bool prevFailed) {
312312
// Activate all of the one-way constraints.
313313
SmallVector<Constraint *, 4> oneWayConstraints;
314314
for (auto &constraint : CS.InactiveConstraints) {
315-
if (constraint.getKind() == ConstraintKind::OneWayBind)
315+
if (constraint.isOneWayConstraint())
316316
oneWayConstraints.push_back(&constraint);
317317
}
318318
for (auto constraint : oneWayConstraints) {

lib/Sema/Constraint.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
6666
case ConstraintKind::FunctionInput:
6767
case ConstraintKind::FunctionResult:
6868
case ConstraintKind::OpaqueUnderlyingType:
69-
case ConstraintKind::OneWayBind:
69+
case ConstraintKind::OneWayEqual:
7070
assert(!First.isNull());
7171
assert(!Second.isNull());
7272
break;
@@ -135,7 +135,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third,
135135
case ConstraintKind::FunctionInput:
136136
case ConstraintKind::FunctionResult:
137137
case ConstraintKind::OpaqueUnderlyingType:
138-
case ConstraintKind::OneWayBind:
138+
case ConstraintKind::OneWayEqual:
139139
llvm_unreachable("Wrong constructor");
140140

141141
case ConstraintKind::KeyPath:
@@ -239,7 +239,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const {
239239
case ConstraintKind::FunctionInput:
240240
case ConstraintKind::FunctionResult:
241241
case ConstraintKind::OpaqueUnderlyingType:
242-
case ConstraintKind::OneWayBind:
242+
case ConstraintKind::OneWayEqual:
243243
return create(cs, getKind(), getFirstType(), getSecondType(), getLocator());
244244

245245
case ConstraintKind::BindOverload:
@@ -312,7 +312,7 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const {
312312
case ConstraintKind::DynamicTypeOf: Out << " dynamicType type of "; break;
313313
case ConstraintKind::EscapableFunctionOf: Out << " @escaping type of "; break;
314314
case ConstraintKind::OpenedExistentialOf: Out << " opened archetype of "; break;
315-
case ConstraintKind::OneWayBind: Out << " one-way bind to "; break;
315+
case ConstraintKind::OneWayEqual: Out << " one-way bind to "; break;
316316
case ConstraintKind::KeyPath:
317317
Out << " key path from ";
318318
getSecondType()->print(Out);
@@ -521,7 +521,7 @@ gatherReferencedTypeVars(Constraint *constraint,
521521
case ConstraintKind::FunctionInput:
522522
case ConstraintKind::FunctionResult:
523523
case ConstraintKind::OpaqueUnderlyingType:
524-
case ConstraintKind::OneWayBind:
524+
case ConstraintKind::OneWayEqual:
525525
constraint->getFirstType()->getTypeVariables(typeVars);
526526
constraint->getSecondType()->getTypeVariables(typeVars);
527527
break;

lib/Sema/Constraint.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ enum class ConstraintKind : char {
150150
/// The first type is a type that's a candidate to be the underlying type of
151151
/// the second opaque archetype.
152152
OpaqueUnderlyingType,
153-
/// The first type will be bound to the second type, but only when the
153+
/// The first type will be equal to the second type, but only when the
154154
/// second type has been fully determined (and mapped down to a concrete
155-
/// type). At that point, this constraint will be treated like a `Bind`
155+
/// type). At that point, this constraint will be treated like an `Equal`
156156
/// constraint.
157-
OneWayBind,
157+
OneWayEqual,
158158
};
159159

160160
/// Classification of the different kinds of constraints.
@@ -495,7 +495,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
495495
case ConstraintKind::BindOverload:
496496
case ConstraintKind::OptionalObject:
497497
case ConstraintKind::OpaqueUnderlyingType:
498-
case ConstraintKind::OneWayBind:
498+
case ConstraintKind::OneWayEqual:
499499
return ConstraintClassification::Relational;
500500

501501
case ConstraintKind::ValueMember:
@@ -609,6 +609,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
609609
/// e.g. coercion constraint "as X" which forms a disjunction.
610610
bool isExplicitConversion() const;
611611

612+
/// Whether this is a one-way constraint.
613+
bool isOneWayConstraint() const {
614+
return Kind == ConstraintKind::OneWayEqual;
615+
}
616+
612617
/// Retrieve the overload choice for an overload-binding constraint.
613618
OverloadChoice getOverloadChoice() const {
614619
assert(Kind == ConstraintKind::BindOverload);

lib/Sema/ConstraintGraph.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
384384
// For a one-way constraint, only consider it when the type variable
385385
// is on the right-hand side of the the binding, and the left-hand side of
386386
// the binding is one of the type variables currently under consideration.
387-
if (constraint->getKind() == ConstraintKind::OneWayBind) {
387+
if (constraint->isOneWayConstraint()) {
388388
auto lhsTypeVar =
389389
constraint->getFirstType()->castTo<TypeVariableType>();
390390
if (!CS.isActiveTypeVariable(lhsTypeVar))
@@ -633,7 +633,7 @@ namespace {
633633
continue;
634634

635635
TypeVariableType *typeVar;
636-
if (constraint.getKind() == ConstraintKind::OneWayBind) {
636+
if (constraint.isOneWayConstraint()) {
637637
// For one-way constraints, associate the constraint with the
638638
// left-hand type variable.
639639
typeVar = constraint.getFirstType()->castTo<TypeVariableType>();
@@ -780,7 +780,7 @@ namespace {
780780
},
781781
[&](Constraint *constraint) {
782782
// Record and skip one-way constraints.
783-
if (constraint->getKind() == ConstraintKind::OneWayBind) {
783+
if (constraint->isOneWayConstraint()) {
784784
oneWayConstraints.push_back(constraint);
785785
return false;
786786
}

test/Constraints/function_builder_one_way.swift

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// RUN: %target-typecheck-verify-swift -enable-function-builder-one-way-constraints
12
// RUN: %target-typecheck-verify-swift -debug-constraints -enable-function-builder-one-way-constraints > %t.log 2>&1
23
// RUN: %FileCheck %s < %t.log
34

@@ -49,23 +50,23 @@ func tuplify<C: Collection, T>(_ collection: C, @TupleBuilder body: (C.Element)
4950

5051
// CHECK: ---Connected components---
5152
// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T69 depends on 1
52-
// CHECK-NEXT: 1: $T9 $T11 $T13 $T16 $T30 $T62 $T63 $T64 $T65 $T66 $T67 $T68 depends on 2, 3, 4, 5, 6
53-
// CHECK-NEXT: 6: $T32 $T43 $T44 $T45 $T46 $T47 $T57 $T58 $T59 $T60 $T61 depends on 7, 10
54-
// CHECK-NEXT: 10: $T48 $T54 $T55 $T56 depends on 11
55-
// CHECK-NEXT: 11: $T49 $T50 $T51 $T52 $T53
56-
// CHECK-NEXT: 7: $T33 $T35 $T39 $T40 $T41 $T42 depends on 8, 9
57-
// CHECK-NEXT: 9: $T36 $T37 $T38
58-
// CHECK-NEXT: 8: $T34
59-
// CHECK-NEXT: 5: $T17 $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 $T28 $T29
60-
// CHECK-NEXT: 4: $T14 $T15
61-
// CHECK-NEXT: 3: $T12
53+
// CHECK-NEXT: 1: $T9 $T11 $T16 $T30 $T62 $T63 $T64 $T65 $T66 $T67 $T68 depends on 2, 3, 4, 5
54+
// CHECK-NEXT: 5: $T32 $T43 $T44 $T45 $T46 $T47 $T57 $T58 $T59 $T60 $T61 depends on 6, 9
55+
// CHECK-NEXT: 9: $T48 $T54 $T55 $T56 depends on 10
56+
// CHECK-NEXT: 10: $T49 $T50 $T51 $T52 $T53
57+
// CHECK-NEXT: 6: $T33 $T35 $T39 $T40 $T41 $T42 depends on 7, 8
58+
// CHECK-NEXT: 8: $T36 $T37 $T38
59+
// CHECK-NEXT: 7: $T34
60+
// CHECK-NEXT: 4: $T17 $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 $T28 $T29
61+
// CHECK-NEXT: 3: $T14 $T15
6262
// CHECK-NEXT: 2: $T10
6363
let names = ["Alice", "Bob", "Charlie"]
6464
let b = true
65+
var number = 17
6566
print(
6667
tuplify(names) { name in
6768
17
68-
3.14159
69+
number
6970
"Hello, \(name)"
7071
tuplify(["a", "b"]) { value in
7172
value.first!
@@ -74,6 +75,6 @@ print(
7475
2.71828
7576
["if", "stmt"]
7677
} else {
77-
[1, 2, 3, 4]
78+
[1, 2, 3, 17]
7879
}
7980
})

0 commit comments

Comments
 (0)