Skip to content

Commit f7ee402

Browse files
authored
Merge pull request #28400 from xedin/rdar-57201781
[ConstraintSystem] Introduce notion of constraint system phase
2 parents 486e2e7 + e3a4b4f commit f7ee402

File tree

7 files changed

+92
-4
lines changed

7 files changed

+92
-4
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3851,6 +3851,10 @@ bool FailureDiagnosis::diagnoseExprFailure() {
38513851
/// This is guaranteed to always emit an error message.
38523852
///
38533853
void ConstraintSystem::diagnoseFailureForExpr(Expr *expr) {
3854+
setPhase(ConstraintSystemPhase::Diagnostics);
3855+
3856+
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
3857+
38543858
// Continue simplifying any active constraints left in the system. We can end
38553859
// up with them because the solver bails out as soon as it sees a Failure. We
38563860
// don't want to leave them around in the system because later diagnostics

lib/Sema/CSGen.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ namespace {
917917
class ConstraintGenerator : public ExprVisitor<ConstraintGenerator, Type> {
918918
ConstraintSystem &CS;
919919
DeclContext *CurDC;
920+
ConstraintSystemPhase CurrPhase;
920921
SmallVector<DeclContext*, 4> DCStack;
921922

922923
static const unsigned numEditorPlaceholderVariables = 2;
@@ -1108,9 +1109,16 @@ namespace {
11081109

11091110
public:
11101111
ConstraintGenerator(ConstraintSystem &CS, DeclContext *DC)
1111-
: CS(CS), CurDC(DC ? DC : CS.DC) { }
1112+
: CS(CS), CurDC(DC ? DC : CS.DC), CurrPhase(CS.getPhase()) {
1113+
// Although constraint system is initialized in `constraint
1114+
// generation` phase, we have to set it here manually because e.g.
1115+
// function builders could generate constraints for its body
1116+
// in the middle of the solving.
1117+
CS.setPhase(ConstraintSystemPhase::ConstraintGeneration);
1118+
}
11121119

11131120
virtual ~ConstraintGenerator() {
1121+
CS.setPhase(CurrPhase);
11141122
// We really ought to have this assertion:
11151123
// assert(DCStack.empty() && CurDC == CS.DC);
11161124
// Unfortunately, ASTWalker is really bad at letting us establish

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6049,7 +6049,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
60496049
// subscript dispatch relies on presence of function application.
60506050
if (result.ViableCandidates.size() == 1) {
60516051
auto &choice = result.ViableCandidates.front();
6052-
if (!solverState && choice.isKeyPathDynamicMemberLookup() &&
6052+
if (Phase == ConstraintSystemPhase::ConstraintGeneration &&
6053+
choice.isKeyPathDynamicMemberLookup() &&
60536054
member.getBaseName().isSubscript()) {
60546055
// Let's move this constraint to the active
60556056
// list so it could be picked up right after

lib/Sema/CSSolver.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,10 @@ bool ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions,
12981298
void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
12991299
assert(solverState);
13001300

1301+
setPhase(ConstraintSystemPhase::Solving);
1302+
1303+
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
1304+
13011305
// If constraint system failed while trying to
13021306
// genenerate constraints, let's stop right here.
13031307
if (failedConstraint)
@@ -1449,7 +1453,7 @@ ConstraintSystem::filterDisjunction(
14491453
// Early simplification of the "keypath dynamic member lookup" choice
14501454
// is impossible because it requires constraints associated with
14511455
// subscript index expression to be present.
1452-
if (!solverState)
1456+
if (Phase == ConstraintSystemPhase::ConstraintGeneration)
14531457
return SolutionKind::Unsolved;
14541458

14551459
for (auto *currentChoice : disjunction->getNestedConstraints()) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,8 @@ SolutionResult ConstraintSystem::salvage() {
24712471
log << "---Attempting to salvage and emit diagnostics---\n";
24722472
}
24732473

2474+
setPhase(ConstraintSystemPhase::Diagnostics);
2475+
24742476
// Attempt to solve again, capturing all states that come from our attempts to
24752477
// select overloads or bind type variables.
24762478
//
@@ -3526,4 +3528,4 @@ Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
35263528

35273529
cacheExprTypes(result);
35283530
return result;
3529-
}
3531+
}

lib/Sema/ConstraintSystem.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,13 @@ struct DynamicCallableMethods {
995995
}
996996
};
997997

998+
enum class ConstraintSystemPhase {
999+
ConstraintGeneration,
1000+
Solving,
1001+
Diagnostics,
1002+
Finalization
1003+
};
1004+
9981005
/// Describes a system of constraints on type variables, the
9991006
/// solution of which assigns concrete types to each of the type variables.
10001007
/// Constraint systems are typically generated given an (untyped) expression.
@@ -1038,6 +1045,9 @@ class ConstraintSystem {
10381045
unsigned CountDisjunctions = 0;
10391046

10401047
private:
1048+
/// Current phase of the constraint system lifetime.
1049+
ConstraintSystemPhase Phase = ConstraintSystemPhase::ConstraintGeneration;
1050+
10411051
/// The set of expressions for which we have generated constraints.
10421052
llvm::SetVector<Expr *> InputExprs;
10431053

@@ -1526,6 +1536,41 @@ class ConstraintSystem {
15261536
};
15271537

15281538
public:
1539+
ConstraintSystemPhase getPhase() const { return Phase; }
1540+
1541+
/// Move constraint system to a new phase of its lifetime.
1542+
void setPhase(ConstraintSystemPhase newPhase) {
1543+
if (Phase == newPhase)
1544+
return;
1545+
1546+
#ifndef NDEBUG
1547+
switch (Phase) {
1548+
case ConstraintSystemPhase::ConstraintGeneration:
1549+
assert(newPhase == ConstraintSystemPhase::Solving);
1550+
break;
1551+
1552+
case ConstraintSystemPhase::Solving:
1553+
// We can come back to constraint generation phase while
1554+
// processing function builder body.
1555+
assert(newPhase == ConstraintSystemPhase::ConstraintGeneration ||
1556+
newPhase == ConstraintSystemPhase::Diagnostics ||
1557+
newPhase == ConstraintSystemPhase::Finalization);
1558+
break;
1559+
1560+
case ConstraintSystemPhase::Diagnostics:
1561+
assert(newPhase == ConstraintSystemPhase::Solving ||
1562+
newPhase == ConstraintSystemPhase::Finalization);
1563+
break;
1564+
1565+
case ConstraintSystemPhase::Finalization:
1566+
assert(newPhase == ConstraintSystemPhase::Diagnostics);
1567+
break;
1568+
}
1569+
#endif
1570+
1571+
Phase = newPhase;
1572+
}
1573+
15291574
/// Cache the types of the given expression and all subexpressions.
15301575
void cacheExprTypes(Expr *expr) {
15311576
bool excludeRoot = false;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-typecheck-verify-swift -target x86_64-apple-macosx10.15 -swift-version 5
2+
// REQUIRES: objc_interop
3+
// REQUIRES: OS=macosx
4+
5+
import SwiftUI
6+
7+
struct ContentView : View {
8+
@State var foo: [String] = Array(repeating: "", count: 5)
9+
10+
var body: some View {
11+
VStack {
12+
HStack { // expected-error {{ambiguous reference to member 'buildBlock()'}}
13+
Text("")
14+
TextFi // expected-error {{use of unresolved identifier 'TextFi'}}
15+
}
16+
17+
ForEach(0 ... 4, id: \.self) { i in
18+
HStack {
19+
TextField("", text: self.$foo[i])
20+
}
21+
}
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)