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