@@ -2892,13 +2892,15 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
28922892 return hadError;
28932893}
28942894
2895- auto TypeChecker::typeCheckForEachBinding (
2896- DeclContext *dc, ForEachStmt *stmt) -> Optional<ForEachBinding> {
2895+ bool TypeChecker::typeCheckForEachBinding (DeclContext *dc, ForEachStmt *stmt) {
28972896 // / Type checking listener for for-each binding.
28982897 class BindingListener : public ExprTypeCheckListener {
28992898 // / The for-each statement.
29002899 ForEachStmt *Stmt;
29012900
2901+ // / The declaration context in which this for-each statement resides.
2902+ DeclContext *DC;
2903+
29022904 // / The locator we're using.
29032905 ConstraintLocator *Locator;
29042906
@@ -2927,7 +2929,8 @@ auto TypeChecker::typeCheckForEachBinding(
29272929 Type IteratorType;
29282930
29292931 public:
2930- explicit BindingListener (ForEachStmt *stmt) : Stmt(stmt) { }
2932+ explicit BindingListener (ForEachStmt *stmt, DeclContext *dc)
2933+ : Stmt(stmt), DC(dc) { }
29312934
29322935 bool builtConstraints (ConstraintSystem &cs, Expr *expr) override {
29332936 // Save the locator we're using for the expression.
@@ -2957,6 +2960,25 @@ auto TypeChecker::typeCheckForEachBinding(
29572960 auto elementLocator = cs.getConstraintLocator (
29582961 ContextualLocator, ConstraintLocator::SequenceElementType);
29592962
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+
29602982 // Collect constraints from the element pattern.
29612983 auto pattern = Stmt->getPattern ();
29622984 InitType = cs.generateConstraints (pattern, elementLocator);
@@ -2985,13 +3007,12 @@ auto TypeChecker::typeCheckForEachBinding(
29853007 }
29863008
29873009 // Reference the makeIterator witness.
2988- ASTContext &ctx = cs.getASTContext ();
29893010 FuncDecl *makeIterator = ctx.getSequenceMakeIterator ();
29903011 Type makeIteratorType =
29913012 cs.createTypeVariable (Locator, TVO_CanBindToNoEscape);
29923013 cs.addValueWitnessConstraint (
29933014 LValueType::get (SequenceType), makeIterator,
2994- makeIteratorType, cs. DC , FunctionRefKind::Compound,
3015+ makeIteratorType, DC, FunctionRefKind::Compound,
29953016 ContextualLocator);
29963017
29973018 Stmt->setSequence (expr);
@@ -3001,6 +3022,7 @@ auto TypeChecker::typeCheckForEachBinding(
30013022 Expr *appliedSolution (Solution &solution, Expr *expr) override {
30023023 // Figure out what types the constraints decided on.
30033024 auto &cs = solution.getConstraintSystem ();
3025+ ASTContext &ctx = cs.getASTContext ();
30043026 InitType = solution.simplifyType (InitType);
30053027 SequenceType = solution.simplifyType (SequenceType);
30063028 ElementType = solution.simplifyType (ElementType);
@@ -3012,17 +3034,17 @@ auto TypeChecker::typeCheckForEachBinding(
30123034
30133035 cs.cacheExprTypes (expr);
30143036 Stmt->setSequence (expr);
3037+ solution.setExprTypes (expr);
30153038
30163039 // Apply the solution to the iteration pattern as well.
30173040 Pattern *pattern = Stmt->getPattern ();
30183041 TypeResolutionOptions options (TypeResolverContext::ForEachStmt);
30193042 options |= TypeResolutionFlags::OverrideType;
30203043 if (TypeChecker::coercePatternToType (pattern,
3021- TypeResolution::forContextual (cs. DC ),
3044+ TypeResolution::forContextual (DC),
30223045 InitType, options)) {
30233046 return nullptr ;
30243047 }
3025-
30263048 Stmt->setPattern (pattern);
30273049
30283050 // Get the conformance of the sequence type to the Sequence protocol.
@@ -3032,24 +3054,79 @@ auto TypeChecker::typeCheckForEachBinding(
30323054 " Couldn't find sequence conformance" );
30333055 Stmt->setSequenceConformance (SequenceConformance);
30343056
3035- solution.setExprTypes (expr);
3036- return expr;
3037- }
3057+ // Check the filtering condition.
3058+ // FIXME: This should be pulled into the constraint system itself.
3059+ if (auto *Where = Stmt->getWhere ()) {
3060+ if (!TypeChecker::typeCheckCondition (Where, DC))
3061+ Stmt->setWhere (Where);
3062+ }
30383063
3039- ForEachBinding getBinding () const {
3040- return { SequenceType, SequenceConformance, IteratorType, ElementType };
3064+ // Invoke iterator() to get an iterator from the sequence.
3065+ VarDecl *iterator;
3066+ Type nextResultType = OptionalType::get (ElementType);
3067+ {
3068+ // Create a local variable to capture the iterator.
3069+ std::string name;
3070+ if (auto np = dyn_cast_or_null<NamedPattern>(Stmt->getPattern ()))
3071+ name = " $" +np->getBoundName ().str ().str ();
3072+ name += " $generator" ;
3073+
3074+ iterator = new (ctx) VarDecl (
3075+ /* IsStatic*/ false , VarDecl::Introducer::Var,
3076+ /* IsCaptureList*/ false , Stmt->getInLoc (),
3077+ ctx.getIdentifier (name), DC);
3078+ iterator->setInterfaceType (IteratorType->mapTypeOutOfContext ());
3079+ iterator->setImplicit ();
3080+ Stmt->setIteratorVar (iterator);
3081+
3082+ auto genPat = new (ctx) NamedPattern (iterator);
3083+ genPat->setImplicit ();
3084+
3085+ // TODO: test/DebugInfo/iteration.swift requires this extra info to
3086+ // be around.
3087+ PatternBindingDecl::createImplicit (
3088+ ctx, StaticSpellingKind::None, genPat,
3089+ new (ctx) OpaqueValueExpr (Stmt->getInLoc (), nextResultType),
3090+ DC, /* VarLoc*/ Stmt->getForLoc ());
3091+ }
3092+
3093+ // Create the iterator variable.
3094+ auto *varRef = TypeChecker::buildCheckedRefExpr (
3095+ iterator, DC, DeclNameLoc (Stmt->getInLoc ()), /* implicit*/ true );
3096+ if (varRef)
3097+ Stmt->setIteratorVarRef (varRef);
3098+
3099+ // Convert that Optional<Element> value to the type of the pattern.
3100+ auto optPatternType = OptionalType::get (Stmt->getPattern ()->getType ());
3101+ if (!optPatternType->isEqual (nextResultType)) {
3102+ OpaqueValueExpr *elementExpr =
3103+ new (ctx) OpaqueValueExpr (Stmt->getInLoc (), nextResultType,
3104+ /* isPlaceholder=*/ true );
3105+ Expr *convertElementExpr = elementExpr;
3106+ if (TypeChecker::typeCheckExpression (
3107+ convertElementExpr, DC,
3108+ TypeLoc::withoutLoc (optPatternType),
3109+ CTP_CoerceOperand).isNull ()) {
3110+ return nullptr ;
3111+ }
3112+ elementExpr->setIsPlaceholder (false );
3113+ Stmt->setElementExpr (elementExpr);
3114+ Stmt->setConvertElementExpr (convertElementExpr);
3115+ }
3116+
3117+ return expr;
30413118 }
30423119 };
30433120
3044- BindingListener listener (stmt);
3121+ BindingListener listener (stmt, dc );
30453122 Expr *seq = stmt->getSequence ();
30463123 assert (seq && " type-checking an uninitialized for-each statement?" );
30473124
30483125 // Type-check the for-each loop sequence and element pattern.
30493126 auto resultTy = TypeChecker::typeCheckExpression (seq, dc, &listener);
30503127 if (!resultTy)
3051- return None ;
3052- return listener. getBinding () ;
3128+ return true ;
3129+ return false ;
30533130}
30543131
30553132bool TypeChecker::typeCheckCondition (Expr *&expr, DeclContext *dc) {
0 commit comments