Skip to content

Commit 605ba93

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 94123d2 commit 605ba93

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
@@ -4743,7 +4743,8 @@ namespace {
47434743
}
47444744

47454745
Expr *visitOneWayExpr(OneWayExpr *E) {
4746-
return E->getSubExpr();
4746+
auto type = simplifyType(cs.getType(E));
4747+
return coerceToType(E->getSubExpr(), type, cs.getConstraintLocator(E));
47474748
}
47484749

47494750
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
@@ -3029,7 +3029,7 @@ namespace {
30293029
Type visitOneWayExpr(OneWayExpr *expr) {
30303030
auto locator = CS.getConstraintLocator(expr);
30313031
auto resultTypeVar = CS.createTypeVariable(locator, 0);
3032-
CS.addConstraint(ConstraintKind::OneWayBind, resultTypeVar,
3032+
CS.addConstraint(ConstraintKind::OneWayEqual, resultTypeVar,
30333033
CS.getType(expr->getSubExpr()), locator);
30343034
return resultTypeVar;
30353035
}

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
11001100
case ConstraintKind::BridgingConversion:
11011101
case ConstraintKind::FunctionInput:
11021102
case ConstraintKind::FunctionResult:
1103-
case ConstraintKind::OneWayBind:
1103+
case ConstraintKind::OneWayEqual:
11041104
llvm_unreachable("Not a conversion");
11051105
}
11061106

@@ -1163,7 +1163,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
11631163
case ConstraintKind::ValueMember:
11641164
case ConstraintKind::FunctionInput:
11651165
case ConstraintKind::FunctionResult:
1166-
case ConstraintKind::OneWayBind:
1166+
case ConstraintKind::OneWayEqual:
11671167
return false;
11681168
}
11691169

@@ -1340,7 +1340,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
13401340
case ConstraintKind::BridgingConversion:
13411341
case ConstraintKind::FunctionInput:
13421342
case ConstraintKind::FunctionResult:
1343-
case ConstraintKind::OneWayBind:
1343+
case ConstraintKind::OneWayEqual:
13441344
llvm_unreachable("Not a relational constraint");
13451345
}
13461346

@@ -2487,7 +2487,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
24872487
case ConstraintKind::ValueMember:
24882488
case ConstraintKind::FunctionInput:
24892489
case ConstraintKind::FunctionResult:
2490-
case ConstraintKind::OneWayBind:
2490+
case ConstraintKind::OneWayEqual:
24912491
llvm_unreachable("Not a relational constraint");
24922492
}
24932493
}
@@ -5008,7 +5008,7 @@ ConstraintSystem::simplifyOneWayConstraint(
50085008
}
50095009

50105010
// Translate this constraint into a one-way binding constraint.
5011-
return matchTypes(first, secondSimplified, ConstraintKind::Bind, flags,
5011+
return matchTypes(first, secondSimplified, ConstraintKind::Equal, flags,
50125012
locator);
50135013
}
50145014

@@ -6920,7 +6920,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
69206920
return simplifyFunctionComponentConstraint(kind, first, second,
69216921
subflags, locator);
69226922

6923-
case ConstraintKind::OneWayBind:
6923+
case ConstraintKind::OneWayEqual:
69246924
return simplifyOneWayConstraint(kind, first, second, subflags, locator);
69256925

69266926
case ConstraintKind::ValueMember:
@@ -7279,7 +7279,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
72797279
// Disjunction constraints are never solved here.
72807280
return SolutionKind::Unsolved;
72817281

7282-
case ConstraintKind::OneWayBind:
7282+
case ConstraintKind::OneWayEqual:
72837283
return simplifyOneWayConstraint(constraint.getKind(),
72847284
constraint.getFirstType(),
72857285
constraint.getSecondType(),

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ void ConstraintSystem::ArgumentInfoCollector::walk(Type argType) {
16561656
case ConstraintKind::SelfObjectOfProtocol:
16571657
case ConstraintKind::ConformsTo:
16581658
case ConstraintKind::Defaultable:
1659-
case ConstraintKind::OneWayBind:
1659+
case ConstraintKind::OneWayEqual:
16601660
break;
16611661
}
16621662
}

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.
@@ -494,7 +494,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
494494
case ConstraintKind::BindOverload:
495495
case ConstraintKind::OptionalObject:
496496
case ConstraintKind::OpaqueUnderlyingType:
497-
case ConstraintKind::OneWayBind:
497+
case ConstraintKind::OneWayEqual:
498498
return ConstraintClassification::Relational;
499499

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

611+
/// Whether this is a one-way constraint.
612+
bool isOneWayConstraint() const {
613+
return Kind == ConstraintKind::OneWayEqual;
614+
}
615+
611616
/// Retrieve the overload choice for an overload-binding constraint.
612617
OverloadChoice getOverloadChoice() const {
613618
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 $T10 $T11 $T12 $T13 $T14 $T16 $T18 $T21 $T35 $T67 $T68 depends on 2, 3, 4, 5, 6
53-
// CHECK-NEXT: 6: $T37 $T38 $T39 $T50 $T51 $T52 $T53 $T54 $T64 $T65 $T66 depends on 7, 10
54-
// CHECK-NEXT: 10: $T55 $T56 $T62 $T63 depends on 11
55-
// CHECK-NEXT: 11: $T57 $T58 $T59 $T60 $T61
56-
// CHECK-NEXT: 7: $T40 $T41 $T42 $T44 $T48 $T49 depends on 8, 9
57-
// CHECK-NEXT: 9: $T45 $T46 $T47
58-
// CHECK-NEXT: 8: $T43
59-
// CHECK-NEXT: 5: $T22 $T23 $T24 $T25 $T26 $T27 $T28 $T29 $T30 $T31 $T32 $T33 $T34
60-
// CHECK-NEXT: 4: $T19 $T20
61-
// CHECK-NEXT: 3: $T17
53+
// CHECK-NEXT: 1: $T9 $T10 $T11 $T12 $T13 $T14 $T16 $T21 $T35 $T67 $T68 depends on 2, 3, 4, 5
54+
// CHECK-NEXT: 5: $T37 $T38 $T39 $T50 $T51 $T52 $T53 $T54 $T64 $T65 $T66 depends on 6, 9
55+
// CHECK-NEXT: 9: $T55 $T56 $T62 $T63 depends on 10
56+
// CHECK-NEXT: 10: $T57 $T58 $T59 $T60 $T61
57+
// CHECK-NEXT: 6: $T40 $T41 $T42 $T44 $T48 $T49 depends on 7, 8
58+
// CHECK-NEXT: 8: $T45 $T46 $T47
59+
// CHECK-NEXT: 7: $T43
60+
// CHECK-NEXT: 4: $T22 $T23 $T24 $T25 $T26 $T27 $T28 $T29 $T30 $T31 $T32 $T33 $T34
61+
// CHECK-NEXT: 3: $T19 $T20
6262
// CHECK-NEXT: 2: $T15
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)