@@ -2892,13 +2892,15 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
2892
2892
return hadError;
2893
2893
}
2894
2894
2895
- auto TypeChecker::typeCheckForEachBinding (
2896
- DeclContext *dc, ForEachStmt *stmt) -> Optional<ForEachBinding> {
2895
+ bool TypeChecker::typeCheckForEachBinding (DeclContext *dc, ForEachStmt *stmt) {
2897
2896
// / Type checking listener for for-each binding.
2898
2897
class BindingListener : public ExprTypeCheckListener {
2899
2898
// / The for-each statement.
2900
2899
ForEachStmt *Stmt;
2901
2900
2901
+ // / The declaration context in which this for-each statement resides.
2902
+ DeclContext *DC;
2903
+
2902
2904
// / The locator we're using.
2903
2905
ConstraintLocator *Locator;
2904
2906
@@ -2927,7 +2929,8 @@ auto TypeChecker::typeCheckForEachBinding(
2927
2929
Type IteratorType;
2928
2930
2929
2931
public:
2930
- explicit BindingListener (ForEachStmt *stmt) : Stmt(stmt) { }
2932
+ explicit BindingListener (ForEachStmt *stmt, DeclContext *dc)
2933
+ : Stmt(stmt), DC(dc) { }
2931
2934
2932
2935
bool builtConstraints (ConstraintSystem &cs, Expr *expr) override {
2933
2936
// Save the locator we're using for the expression.
@@ -2957,6 +2960,25 @@ auto TypeChecker::typeCheckForEachBinding(
2957
2960
auto elementLocator = cs.getConstraintLocator (
2958
2961
ContextualLocator, ConstraintLocator::SequenceElementType);
2959
2962
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
+
2960
2982
// Collect constraints from the element pattern.
2961
2983
auto pattern = Stmt->getPattern ();
2962
2984
InitType = cs.generateConstraints (pattern, elementLocator);
@@ -2985,13 +3007,12 @@ auto TypeChecker::typeCheckForEachBinding(
2985
3007
}
2986
3008
2987
3009
// Reference the makeIterator witness.
2988
- ASTContext &ctx = cs.getASTContext ();
2989
3010
FuncDecl *makeIterator = ctx.getSequenceMakeIterator ();
2990
3011
Type makeIteratorType =
2991
3012
cs.createTypeVariable (Locator, TVO_CanBindToNoEscape);
2992
3013
cs.addValueWitnessConstraint (
2993
3014
LValueType::get (SequenceType), makeIterator,
2994
- makeIteratorType, cs. DC , FunctionRefKind::Compound,
3015
+ makeIteratorType, DC, FunctionRefKind::Compound,
2995
3016
ContextualLocator);
2996
3017
2997
3018
Stmt->setSequence (expr);
@@ -3001,6 +3022,7 @@ auto TypeChecker::typeCheckForEachBinding(
3001
3022
Expr *appliedSolution (Solution &solution, Expr *expr) override {
3002
3023
// Figure out what types the constraints decided on.
3003
3024
auto &cs = solution.getConstraintSystem ();
3025
+ ASTContext &ctx = cs.getASTContext ();
3004
3026
InitType = solution.simplifyType (InitType);
3005
3027
SequenceType = solution.simplifyType (SequenceType);
3006
3028
ElementType = solution.simplifyType (ElementType);
@@ -3012,17 +3034,17 @@ auto TypeChecker::typeCheckForEachBinding(
3012
3034
3013
3035
cs.cacheExprTypes (expr);
3014
3036
Stmt->setSequence (expr);
3037
+ solution.setExprTypes (expr);
3015
3038
3016
3039
// Apply the solution to the iteration pattern as well.
3017
3040
Pattern *pattern = Stmt->getPattern ();
3018
3041
TypeResolutionOptions options (TypeResolverContext::ForEachStmt);
3019
3042
options |= TypeResolutionFlags::OverrideType;
3020
3043
if (TypeChecker::coercePatternToType (pattern,
3021
- TypeResolution::forContextual (cs. DC ),
3044
+ TypeResolution::forContextual (DC),
3022
3045
InitType, options)) {
3023
3046
return nullptr ;
3024
3047
}
3025
-
3026
3048
Stmt->setPattern (pattern);
3027
3049
3028
3050
// Get the conformance of the sequence type to the Sequence protocol.
@@ -3032,24 +3054,79 @@ auto TypeChecker::typeCheckForEachBinding(
3032
3054
" Couldn't find sequence conformance" );
3033
3055
Stmt->setSequenceConformance (SequenceConformance);
3034
3056
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
+ }
3038
3063
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;
3041
3118
}
3042
3119
};
3043
3120
3044
- BindingListener listener (stmt);
3121
+ BindingListener listener (stmt, dc );
3045
3122
Expr *seq = stmt->getSequence ();
3046
3123
assert (seq && " type-checking an uninitialized for-each statement?" );
3047
3124
3048
3125
// Type-check the for-each loop sequence and element pattern.
3049
3126
auto resultTy = TypeChecker::typeCheckExpression (seq, dc, &listener);
3050
3127
if (!resultTy)
3051
- return None ;
3052
- return listener. getBinding () ;
3128
+ return true ;
3129
+ return false ;
3053
3130
}
3054
3131
3055
3132
bool TypeChecker::typeCheckCondition (Expr *&expr, DeclContext *dc) {
0 commit comments