@@ -1631,6 +1631,10 @@ bool ExprTypeCheckListener::builtConstraints(ConstraintSystem &cs, Expr *expr) {
1631
1631
return false ;
1632
1632
}
1633
1633
1634
+ Expr *ExprTypeCheckListener::foundSolution (Solution &solution, Expr *expr) {
1635
+ return expr;
1636
+ }
1637
+
1634
1638
Expr *ExprTypeCheckListener::appliedSolution (Solution &solution, Expr *expr) {
1635
1639
return expr;
1636
1640
}
@@ -1864,14 +1868,24 @@ bool TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
1864
1868
expr->setType (ErrorType::get (Context));
1865
1869
return false ;
1866
1870
}
1867
-
1868
- // Apply the solution to the expression.
1871
+
1872
+ auto result = expr;
1869
1873
auto &solution = viable[0 ];
1874
+ if (listener) {
1875
+ result = listener->foundSolution (solution, result);
1876
+ if (!result)
1877
+ return true ;
1878
+ }
1879
+
1880
+ if (options.contains (TypeCheckExprFlags::SkipApplyingSolution))
1881
+ return false ;
1882
+
1883
+ // Apply the solution to the expression.
1870
1884
bool isDiscarded = options.contains (TypeCheckExprFlags::IsDiscarded);
1871
1885
bool skipClosures = options.contains (TypeCheckExprFlags::SkipMultiStmtClosures);
1872
- auto result = cs.applySolution (solution, expr , convertType.getType (),
1873
- isDiscarded, suppressDiagnostics,
1874
- skipClosures);
1886
+ result = cs.applySolution (solution, result , convertType.getType (),
1887
+ isDiscarded, suppressDiagnostics,
1888
+ skipClosures);
1875
1889
if (!result) {
1876
1890
// Failure already diagnosed, above, as part of applying the solution.
1877
1891
return true ;
@@ -2111,26 +2125,25 @@ bool TypeChecker::typeCheckExpressionShallow(Expr *&expr, DeclContext *dc) {
2111
2125
}
2112
2126
2113
2127
bool TypeChecker::typeCheckBinding (Pattern *&pattern, Expr *&initializer,
2114
- DeclContext *DC, bool skipClosures ) {
2128
+ DeclContext *DC, bool skipApplyingSolution ) {
2115
2129
2116
2130
// / Type checking listener for pattern binding initializers.
2117
2131
class BindingListener : public ExprTypeCheckListener {
2118
2132
Pattern *&pattern;
2119
2133
Expr *&initializer;
2120
- DeclContext *DC;
2121
- bool skipClosures;
2122
2134
2123
2135
// / The locator we're using.
2124
2136
ConstraintLocator *Locator;
2125
2137
2126
2138
// / The type of the initializer.
2127
2139
Type InitType;
2128
-
2140
+
2129
2141
public:
2130
- explicit BindingListener (Pattern *&pattern, Expr *&initializer,
2131
- DeclContext *DC, bool skipClosures)
2132
- : pattern(pattern), initializer(initializer), DC(DC),
2133
- skipClosures(skipClosures) { }
2142
+ explicit BindingListener (Pattern *&pattern, Expr *&initializer)
2143
+ : pattern(pattern), initializer(initializer),
2144
+ Locator(nullptr ) { }
2145
+
2146
+ Type getInitType () const { return InitType; }
2134
2147
2135
2148
bool builtConstraints (ConstraintSystem &cs, Expr *expr) override {
2136
2149
// Save the locator we're using for the expression.
@@ -2150,44 +2163,32 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
2150
2163
return false ;
2151
2164
}
2152
2165
2153
- Expr *appliedSolution (Solution &solution, Expr *expr) override {
2166
+ Expr *foundSolution (Solution &solution, Expr *expr) override {
2154
2167
// Figure out what type the constraints decided on.
2155
- auto &cs = solution.getConstraintSystem ();
2156
- auto &tc = cs.getTypeChecker ();
2157
2168
InitType = solution.simplifyType (InitType);
2158
2169
2170
+ // Just keep going.
2171
+ return expr;
2172
+ }
2173
+
2174
+ Expr *appliedSolution (Solution &solution, Expr *expr) override {
2159
2175
// Convert the initializer to the type of the pattern.
2160
2176
// ignoreTopLevelInjection = Binding->isConditional()
2161
2177
expr = solution.coerceToType (expr, InitType, Locator,
2162
- false /* ignoreTopLevelInjection */ ,
2163
- skipClosures);
2178
+ false /* ignoreTopLevelInjection */ );
2164
2179
if (!expr) {
2165
2180
return nullptr ;
2166
2181
}
2167
2182
2168
- // Force the initializer to be materializable.
2169
- // FIXME: work this into the constraint system
2170
- expr = tc.coerceToMaterializable (expr);
2183
+ assert (expr->getType ()->isEqual (InitType));
2171
2184
2172
- // Apply the solution to the pattern as well.
2173
- Type patternType = expr->getType ();
2174
-
2175
- TypeResolutionOptions options;
2176
- options |= TR_OverrideType;
2177
- options |= TR_InExpression;
2178
- if (isa<EditorPlaceholderExpr>(expr->getSemanticsProvidingExpr ())) {
2179
- options |= TR_EditorPlaceholder;
2180
- }
2181
- if (tc.coercePatternToType (pattern, DC, patternType, options)) {
2182
- return nullptr ;
2183
- }
2184
2185
initializer = expr;
2185
2186
return expr;
2186
2187
}
2187
2188
};
2188
2189
2189
2190
assert (initializer && " type-checking an uninitialized binding?" );
2190
- BindingListener listener (pattern, initializer, DC, skipClosures );
2191
+ BindingListener listener (pattern, initializer);
2191
2192
2192
2193
TypeLoc contextualType;
2193
2194
auto contextualPurpose = CTP_Unused;
@@ -2209,18 +2210,34 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
2209
2210
2210
2211
// Type-check the initializer.
2211
2212
TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
2212
- if (skipClosures )
2213
- flags |= TypeCheckExprFlags::SkipMultiStmtClosures ;
2213
+ if (skipApplyingSolution )
2214
+ flags |= TypeCheckExprFlags::SkipApplyingSolution ;
2214
2215
2215
2216
bool hadError = typeCheckExpression (initializer, DC, contextualType,
2216
2217
contextualPurpose,
2217
2218
flags,
2218
2219
&listener);
2219
-
2220
- if (hadError && !initializer->getType ()) {
2221
- initializer->setType (ErrorType::get (Context));
2220
+
2221
+ if (!hadError) {
2222
+ TypeResolutionOptions options;
2223
+ options |= TR_OverrideType;
2224
+ options |= TR_InExpression;
2225
+ if (isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr ())) {
2226
+ options |= TR_EditorPlaceholder;
2227
+ }
2228
+
2229
+ // Apply the solution to the pattern as well.
2230
+ if (coercePatternToType (pattern, DC, listener.getInitType (), options)) {
2231
+ return true ;
2232
+ }
2222
2233
}
2223
2234
2235
+ if (hadError && !initializer->getType ())
2236
+ initializer->setType (ErrorType::get (Context));
2237
+
2238
+ // If the type of the pattern is inferred, assign error types to the pattern
2239
+ // and its variables, to prevent it from being referenced by the constraint
2240
+ // system.
2224
2241
if (hadError &&
2225
2242
(!pattern->hasType () ||
2226
2243
pattern->getType ()->hasUnboundGenericType ())) {
@@ -2242,7 +2259,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
2242
2259
2243
2260
bool TypeChecker::typeCheckPatternBinding (PatternBindingDecl *PBD,
2244
2261
unsigned patternNumber,
2245
- bool skipClosures ) {
2262
+ bool skipApplyingSolution ) {
2246
2263
2247
2264
Pattern *pattern = PBD->getPattern (patternNumber);
2248
2265
Expr *init = PBD->getInit (patternNumber);
@@ -2262,11 +2279,10 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
2262
2279
DC = initContext;
2263
2280
}
2264
2281
2265
- bool hadError = typeCheckBinding (pattern, init, DC, skipClosures );
2282
+ bool hadError = typeCheckBinding (pattern, init, DC, skipApplyingSolution );
2266
2283
PBD->setPattern (patternNumber, pattern, initContext);
2267
2284
PBD->setInit (patternNumber, init);
2268
2285
2269
-
2270
2286
// If we entered an initializer context, contextualize any
2271
2287
// auto-closures we might have created.
2272
2288
if (initContext) {
@@ -2600,7 +2616,8 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc,
2600
2616
// If the pattern didn't get a type, it's because we ran into some
2601
2617
// unknown types along the way. We'll need to check the initializer.
2602
2618
auto init = elt.getInitializer ();
2603
- hadError |= typeCheckBinding (pattern, init, dc, /* skipClosures*/ false );
2619
+ hadError |= typeCheckBinding (pattern, init, dc,
2620
+ /* skipApplyingSolution*/ false );
2604
2621
elt.setPattern (pattern);
2605
2622
elt.setInitializer (init);
2606
2623
hadAnyFalsable |= pattern->isRefutablePattern ();
@@ -2917,7 +2934,6 @@ bool TypeChecker::convertToType(Expr *&expr, Type type, DeclContext *dc,
2917
2934
Expr *result = solution.coerceToType (expr, type,
2918
2935
cs.getConstraintLocator (expr),
2919
2936
/* ignoreTopLevelInjection*/ false ,
2920
- /* skipClosures*/ false ,
2921
2937
typeFromPattern);
2922
2938
if (!result) {
2923
2939
return true ;
0 commit comments