Skip to content

Commit 7fa84b5

Browse files
committed
[Type checker] Move for-each pattern checking logic into the solver.
1 parent 40e599e commit 7fa84b5

File tree

2 files changed

+33
-29
lines changed

2 files changed

+33
-29
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,6 +2898,9 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
28982898
/// The for-each statement.
28992899
ForEachStmt *Stmt;
29002900

2901+
/// The declaration context in which this for-each statement resides.
2902+
DeclContext *DC;
2903+
29012904
/// The locator we're using.
29022905
ConstraintLocator *Locator;
29032906

@@ -2926,7 +2929,8 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
29262929
Type IteratorType;
29272930

29282931
public:
2929-
explicit BindingListener(ForEachStmt *stmt) : Stmt(stmt) { }
2932+
explicit BindingListener(ForEachStmt *stmt, DeclContext *dc)
2933+
: Stmt(stmt), DC(dc) { }
29302934

29312935
bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
29322936
// Save the locator we're using for the expression.
@@ -2956,6 +2960,25 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
29562960
auto elementLocator = cs.getConstraintLocator(
29572961
ContextualLocator, ConstraintLocator::SequenceElementType);
29582962

2963+
// Check the element pattern.
2964+
ASTContext &ctx = cs.getASTContext();
2965+
if (auto *P = TypeChecker::resolvePattern(Stmt->getPattern(), DC,
2966+
/*isStmtCondition*/false)) {
2967+
Stmt->setPattern(P);
2968+
} else {
2969+
Stmt->getPattern()->setType(ErrorType::get(ctx));
2970+
return true;
2971+
}
2972+
2973+
TypeResolutionOptions options(TypeResolverContext::InExpression);
2974+
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
2975+
options |= TypeResolutionFlags::AllowUnboundGenerics;
2976+
if (TypeChecker::typeCheckPattern(Stmt->getPattern(), DC, options)) {
2977+
// FIXME: Handle errors better.
2978+
Stmt->getPattern()->setType(ErrorType::get(ctx));
2979+
return true;
2980+
}
2981+
29592982
// Collect constraints from the element pattern.
29602983
auto pattern = Stmt->getPattern();
29612984
InitType = cs.generateConstraints(pattern, elementLocator);
@@ -2984,13 +3007,12 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
29843007
}
29853008

29863009
// Reference the makeIterator witness.
2987-
ASTContext &ctx = cs.getASTContext();
29883010
FuncDecl *makeIterator = ctx.getSequenceMakeIterator();
29893011
Type makeIteratorType =
29903012
cs.createTypeVariable(Locator, TVO_CanBindToNoEscape);
29913013
cs.addValueWitnessConstraint(
29923014
LValueType::get(SequenceType), makeIterator,
2993-
makeIteratorType, cs.DC, FunctionRefKind::Compound,
3015+
makeIteratorType, DC, FunctionRefKind::Compound,
29943016
ContextualLocator);
29953017

29963018
Stmt->setSequence(expr);
@@ -3019,7 +3041,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30193041
TypeResolutionOptions options(TypeResolverContext::ForEachStmt);
30203042
options |= TypeResolutionFlags::OverrideType;
30213043
if (TypeChecker::coercePatternToType(pattern,
3022-
TypeResolution::forContextual(cs.DC),
3044+
TypeResolution::forContextual(DC),
30233045
InitType, options)) {
30243046
return nullptr;
30253047
}
@@ -3033,10 +3055,10 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30333055
"Couldn't find sequence conformance");
30343056
Stmt->setSequenceConformance(SequenceConformance);
30353057

3036-
// Check the
3058+
// Check the filtering condition.
30373059
// FIXME: This should be pulled into the constraint system itself.
30383060
if (auto *Where = Stmt->getWhere()) {
3039-
if (!TypeChecker::typeCheckCondition(Where, cs.DC))
3061+
if (!TypeChecker::typeCheckCondition(Where, DC))
30403062
Stmt->setWhere(Where);
30413063
}
30423064

@@ -3053,7 +3075,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30533075
iterator = new (ctx) VarDecl(
30543076
/*IsStatic*/ false, VarDecl::Introducer::Var,
30553077
/*IsCaptureList*/ false, Stmt->getInLoc(),
3056-
ctx.getIdentifier(name), cs.DC);
3078+
ctx.getIdentifier(name), DC);
30573079
iterator->setInterfaceType(IteratorType->mapTypeOutOfContext());
30583080
iterator->setImplicit();
30593081
Stmt->setIteratorVar(iterator);
@@ -3066,12 +3088,12 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30663088
PatternBindingDecl::createImplicit(
30673089
ctx, StaticSpellingKind::None, genPat,
30683090
new (ctx) OpaqueValueExpr(Stmt->getInLoc(), nextResultType),
3069-
cs.DC, /*VarLoc*/ Stmt->getForLoc());
3091+
DC, /*VarLoc*/ Stmt->getForLoc());
30703092
}
30713093

30723094
// Create the iterator variable.
30733095
auto *varRef = TypeChecker::buildCheckedRefExpr(
3074-
iterator, cs.DC, DeclNameLoc(Stmt->getInLoc()), /*implicit*/ true);
3096+
iterator, DC, DeclNameLoc(Stmt->getInLoc()), /*implicit*/ true);
30753097
if (varRef)
30763098
Stmt->setIteratorVarRef(varRef);
30773099

@@ -3083,7 +3105,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30833105
/*isPlaceholder=*/true);
30843106
Expr *convertElementExpr = elementExpr;
30853107
if (TypeChecker::typeCheckExpression(
3086-
convertElementExpr, cs.DC,
3108+
convertElementExpr, DC,
30873109
TypeLoc::withoutLoc(optPatternType),
30883110
CTP_CoerceOperand).isNull()) {
30893111
return nullptr;
@@ -3097,7 +3119,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30973119
}
30983120
};
30993121

3100-
BindingListener listener(stmt);
3122+
BindingListener listener(stmt, dc);
31013123
Expr *seq = stmt->getSequence();
31023124
assert(seq && "type-checking an uninitialized for-each statement?");
31033125

lib/Sema/TypeCheckStmt.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -731,24 +731,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
731731
}
732732

733733
Stmt *visitForEachStmt(ForEachStmt *S) {
734-
TypeResolutionOptions options(TypeResolverContext::InExpression);
735-
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
736-
options |= TypeResolutionFlags::AllowUnboundGenerics;
737-
738-
if (auto *P = TypeChecker::resolvePattern(S->getPattern(), DC,
739-
/*isStmtCondition*/false)) {
740-
S->setPattern(P);
741-
} else {
742-
S->getPattern()->setType(ErrorType::get(getASTContext()));
743-
return nullptr;
744-
}
745-
746-
if (TypeChecker::typeCheckPattern(S->getPattern(), DC, options)) {
747-
// FIXME: Handle errors better.
748-
S->getPattern()->setType(ErrorType::get(getASTContext()));
749-
return nullptr;
750-
}
751-
752734
if (TypeChecker::typeCheckForEachBinding(DC, S))
753735
return nullptr;
754736

0 commit comments

Comments
 (0)