@@ -7886,7 +7886,7 @@ bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
7886
7886
7887
7887
// / Apply the given solution to the initialization target.
7888
7888
// /
7889
- // / \returns the resulting initialiation expression.
7889
+ // / \returns the resulting initialization expression.
7890
7890
static Optional<SolutionApplicationTarget> applySolutionToInitialization (
7891
7891
Solution &solution, SolutionApplicationTarget target,
7892
7892
Expr *initializer) {
@@ -7950,7 +7950,7 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
7950
7950
finalPatternType = finalPatternType->reconstituteSugar (/* recursive =*/ false );
7951
7951
7952
7952
// Apply the solution to the pattern as well.
7953
- auto contextualPattern = target.getInitializationContextualPattern ();
7953
+ auto contextualPattern = target.getContextualPattern ();
7954
7954
if (auto coercedPattern = TypeChecker::coercePatternToType (
7955
7955
contextualPattern, finalPatternType, options)) {
7956
7956
resultTarget.setPattern (coercedPattern);
@@ -7961,6 +7961,139 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
7961
7961
return resultTarget;
7962
7962
}
7963
7963
7964
+ // / Apply the given solution to the for-each statement target.
7965
+ // /
7966
+ // / \returns the resulting initialization expression.
7967
+ static Optional<SolutionApplicationTarget> applySolutionToForEachStmt (
7968
+ Solution &solution, SolutionApplicationTarget target, Expr *sequence) {
7969
+ auto resultTarget = target;
7970
+ auto &forEachStmtInfo = resultTarget.getForEachStmtInfo ();
7971
+
7972
+ // Simplify the various types.
7973
+ forEachStmtInfo.elementType =
7974
+ solution.simplifyType (forEachStmtInfo.elementType );
7975
+ forEachStmtInfo.iteratorType =
7976
+ solution.simplifyType (forEachStmtInfo.iteratorType );
7977
+ forEachStmtInfo.initType =
7978
+ solution.simplifyType (forEachStmtInfo.initType );
7979
+ forEachStmtInfo.sequenceType =
7980
+ solution.simplifyType (forEachStmtInfo.sequenceType );
7981
+
7982
+ // Coerce the sequence to the sequence type.
7983
+ auto &cs = solution.getConstraintSystem ();
7984
+ auto locator = cs.getConstraintLocator (target.getAsExpr ());
7985
+ sequence = solution.coerceToType (
7986
+ sequence, forEachStmtInfo.sequenceType , locator);
7987
+ if (!sequence)
7988
+ return None;
7989
+
7990
+ resultTarget.setExpr (sequence);
7991
+
7992
+ // Get the conformance of the sequence type to the Sequence protocol.
7993
+ auto stmt = forEachStmtInfo.stmt ;
7994
+ auto sequenceProto = TypeChecker::getProtocol (
7995
+ cs.getASTContext (), stmt->getForLoc (), KnownProtocolKind::Sequence);
7996
+ auto contextualLocator = cs.getConstraintLocator (
7997
+ target.getAsExpr (), LocatorPathElt::ContextualType ());
7998
+ auto sequenceConformance = solution.resolveConformance (
7999
+ contextualLocator, sequenceProto);
8000
+ assert (!sequenceConformance.isInvalid () &&
8001
+ " Couldn't find sequence conformance" );
8002
+
8003
+ // Coerce the pattern to the element type.
8004
+ TypeResolutionOptions options (TypeResolverContext::ForEachStmt);
8005
+ options |= TypeResolutionFlags::OverrideType;
8006
+
8007
+ // Apply the solution to the pattern as well.
8008
+ auto contextualPattern = target.getContextualPattern ();
8009
+ if (auto coercedPattern = TypeChecker::coercePatternToType (
8010
+ contextualPattern, forEachStmtInfo.initType , options)) {
8011
+ resultTarget.setPattern (coercedPattern);
8012
+ } else {
8013
+ return None;
8014
+ }
8015
+
8016
+ // Apply the solution to the filtering condition, if there is one.
8017
+ auto dc = target.getDeclContext ();
8018
+ if (forEachStmtInfo.whereExpr ) {
8019
+ auto *boolDecl = dc->getASTContext ().getBoolDecl ();
8020
+ assert (boolDecl);
8021
+ Type boolType = boolDecl->getDeclaredType ();
8022
+ assert (boolType);
8023
+
8024
+ SolutionApplicationTarget whereTarget (
8025
+ forEachStmtInfo.whereExpr , dc, CTP_Condition, boolType,
8026
+ /* isDiscarded=*/ false );
8027
+ auto newWhereTarget = cs.applySolution (solution, whereTarget);
8028
+ if (!newWhereTarget)
8029
+ return None;
8030
+
8031
+ forEachStmtInfo.whereExpr = newWhereTarget->getAsExpr ();
8032
+ }
8033
+
8034
+ // Invoke iterator() to get an iterator from the sequence.
8035
+ ASTContext &ctx = cs.getASTContext ();
8036
+ VarDecl *iterator;
8037
+ Type nextResultType = OptionalType::get (forEachStmtInfo.elementType );
8038
+ {
8039
+ // Create a local variable to capture the iterator.
8040
+ std::string name;
8041
+ if (auto np = dyn_cast_or_null<NamedPattern>(stmt->getPattern ()))
8042
+ name = " $" +np->getBoundName ().str ().str ();
8043
+ name += " $generator" ;
8044
+
8045
+ iterator = new (ctx) VarDecl (
8046
+ /* IsStatic*/ false , VarDecl::Introducer::Var,
8047
+ /* IsCaptureList*/ false , stmt->getInLoc (),
8048
+ ctx.getIdentifier (name), dc);
8049
+ iterator->setInterfaceType (
8050
+ forEachStmtInfo.iteratorType ->mapTypeOutOfContext ());
8051
+ iterator->setImplicit ();
8052
+
8053
+ auto genPat = new (ctx) NamedPattern (iterator);
8054
+ genPat->setImplicit ();
8055
+
8056
+ // TODO: test/DebugInfo/iteration.swift requires this extra info to
8057
+ // be around.
8058
+ PatternBindingDecl::createImplicit (
8059
+ ctx, StaticSpellingKind::None, genPat,
8060
+ new (ctx) OpaqueValueExpr (stmt->getInLoc (), nextResultType),
8061
+ dc, /* VarLoc*/ stmt->getForLoc ());
8062
+ }
8063
+
8064
+ // Create the iterator variable.
8065
+ auto *varRef = TypeChecker::buildCheckedRefExpr (
8066
+ iterator, dc, DeclNameLoc (stmt->getInLoc ()), /* implicit*/ true );
8067
+
8068
+ // Convert that Optional<Element> value to the type of the pattern.
8069
+ auto optPatternType = OptionalType::get (forEachStmtInfo.initType );
8070
+ if (!optPatternType->isEqual (nextResultType)) {
8071
+ OpaqueValueExpr *elementExpr =
8072
+ new (ctx) OpaqueValueExpr (stmt->getInLoc (), nextResultType,
8073
+ /* isPlaceholder=*/ true );
8074
+ Expr *convertElementExpr = elementExpr;
8075
+ if (TypeChecker::typeCheckExpression (
8076
+ convertElementExpr, dc,
8077
+ TypeLoc::withoutLoc (optPatternType),
8078
+ CTP_CoerceOperand).isNull ()) {
8079
+ return None;
8080
+ }
8081
+ elementExpr->setIsPlaceholder (false );
8082
+ stmt->setElementExpr (elementExpr);
8083
+ stmt->setConvertElementExpr (convertElementExpr);
8084
+ }
8085
+
8086
+ // Write the result back into the AST.
8087
+ stmt->setSequence (resultTarget.getAsExpr ());
8088
+ stmt->setPattern (resultTarget.getContextualPattern ().getPattern ());
8089
+ stmt->setSequenceConformance (sequenceConformance);
8090
+ stmt->setWhere (forEachStmtInfo.whereExpr );
8091
+ stmt->setIteratorVar (iterator);
8092
+ stmt->setIteratorVarRef (varRef);
8093
+
8094
+ return resultTarget;
8095
+ }
8096
+
7964
8097
Optional<SolutionApplicationTarget>
7965
8098
ExprWalker::rewriteTarget (SolutionApplicationTarget target) {
7966
8099
auto &solution = Rewriter.solution ;
@@ -7972,16 +8105,50 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
7972
8105
if (!rewrittenExpr)
7973
8106
return None;
7974
8107
7975
- // / Handle application for initializations.
7976
- if (target.getExprContextualTypePurpose () == CTP_Initialization) {
8108
+ // / Handle special cases for expressions.
8109
+ switch (target.getExprContextualTypePurpose ()) {
8110
+ case CTP_Initialization: {
7977
8111
auto initResultTarget = applySolutionToInitialization (
7978
8112
solution, target, rewrittenExpr);
7979
8113
if (!initResultTarget)
7980
8114
return None;
7981
8115
7982
8116
result = *initResultTarget;
7983
- } else {
8117
+ break ;
8118
+ }
8119
+
8120
+ case CTP_ForEachStmt: {
8121
+ auto forEachResultTarget = applySolutionToForEachStmt (
8122
+ solution, target, rewrittenExpr);
8123
+ if (!forEachResultTarget)
8124
+ return None;
8125
+
8126
+ result = *forEachResultTarget;
8127
+ break ;
8128
+ }
8129
+
8130
+ case CTP_Unused:
8131
+ case CTP_ReturnStmt:
8132
+ case swift::CTP_ReturnSingleExpr:
8133
+ case swift::CTP_YieldByValue:
8134
+ case swift::CTP_YieldByReference:
8135
+ case swift::CTP_ThrowStmt:
8136
+ case swift::CTP_EnumCaseRawValue:
8137
+ case swift::CTP_DefaultParameter:
8138
+ case swift::CTP_AutoclosureDefaultParameter:
8139
+ case swift::CTP_CalleeResult:
8140
+ case swift::CTP_CallArgument:
8141
+ case swift::CTP_ClosureResult:
8142
+ case swift::CTP_ArrayElement:
8143
+ case swift::CTP_DictionaryKey:
8144
+ case swift::CTP_DictionaryValue:
8145
+ case swift::CTP_CoerceOperand:
8146
+ case swift::CTP_AssignSource:
8147
+ case swift::CTP_SubscriptAssignSource:
8148
+ case swift::CTP_Condition:
8149
+ case swift::CTP_CannotFail:
7984
8150
result.setExpr (rewrittenExpr);
8151
+ break ;
7985
8152
}
7986
8153
} else if (auto stmtCondition = target.getAsStmtCondition ()) {
7987
8154
for (auto &condElement : *stmtCondition) {
0 commit comments