@@ -133,95 +133,160 @@ bool ConstraintSystem::generateConstraints(
133
133
134
134
// MARK: Solution application
135
135
136
- // / Coerce the body of the given closure expression so that it returns
137
- // / Void rather than the value in it.
138
- static void coerceClosureExprToVoid (
139
- Solution &solution, ClosureExpr *closure) {
140
- auto &cs = solution.getConstraintSystem ();
141
- auto &ctx = cs.getASTContext ();
142
-
143
- // Re-write the single-expression closure to return '()'
144
- assert (closure->hasSingleExpressionBody ());
145
-
146
- // A single-expression body contains a single return statement
147
- // prior to this transformation.
148
- auto member = closure->getBody ()->getFirstElement ();
149
-
150
- if (member.is <Stmt *>()) {
151
- auto returnStmt = cast<ReturnStmt>(member.get <Stmt *>());
152
- auto singleExpr = returnStmt->getResult ();
153
- auto voidExpr = cs.cacheType (TupleExpr::createEmpty (
154
- ctx, singleExpr->getStartLoc (), singleExpr->getEndLoc (),
155
- /* implicit*/ true ));
156
- returnStmt->setResult (voidExpr);
157
-
158
- // For l-value types, reset to the object type. This might not be strictly
159
- // necessary any more, but it's probably still a good idea.
160
- if (cs.getType (singleExpr)->is <LValueType>())
161
- cs.setType (singleExpr,
162
- cs.getType (singleExpr)->getWithoutSpecifierType ());
163
-
164
- solution.setExprTypes (singleExpr);
165
- TypeChecker::checkIgnoredExpr (singleExpr);
166
-
167
- SmallVector<ASTNode, 2 > elements;
168
- elements.push_back (singleExpr);
169
- elements.push_back (returnStmt);
170
-
171
- auto braceStmt = BraceStmt::create (ctx, closure->getStartLoc (),
172
- elements, closure->getEndLoc (),
173
- /* implicit*/ true );
174
-
175
- closure->setImplicit ();
176
- closure->setBody (braceStmt, /* isSingleExpression*/ true );
136
+ namespace {
137
+
138
+ // / Statement visitor that applies constraints for a given closure body.
139
+ class ClosureConstraintApplication
140
+ : public StmtVisitor<ClosureConstraintApplication, ASTNode> {
141
+ friend StmtVisitor<ClosureConstraintApplication, ASTNode>;
142
+
143
+ Solution &solution;
144
+ ClosureExpr *closure;
145
+ Type resultType;
146
+ RewriteTargetFn rewriteTarget;
147
+ bool isSingleExpression;
148
+
149
+ public:
150
+ // / Whether an error was encountered while generating constraints.
151
+ bool hadError = false ;
152
+
153
+ ClosureConstraintApplication (
154
+ Solution &solution, ClosureExpr *closure, Type resultType,
155
+ RewriteTargetFn rewriteTarget)
156
+ : solution(solution), closure(closure), resultType(resultType),
157
+ rewriteTarget (rewriteTarget),
158
+ isSingleExpression(closure->hasSingleExpressionBody ()) { }
159
+
160
+ private:
161
+ // / Rewrite an expression without any particularly special context.
162
+ Expr *rewriteExpr (Expr *expr) {
163
+ auto result = rewriteTarget (
164
+ SolutionApplicationTarget (expr, closure, CTP_Unused, Type (),
165
+ /* isDiscarded=*/ false ));
166
+ if (result)
167
+ return result->getAsExpr ();
168
+
169
+ return nullptr ;
177
170
}
178
171
179
- // Finally, compute the proper type for the closure.
180
- auto fnType = cs.getType (closure)->getAs <FunctionType>();
181
- auto newClosureType = FunctionType::get (
182
- fnType->getParams (), ctx.TheEmptyTupleType , fnType->getExtInfo ());
183
- cs.setType (closure, newClosureType);
184
- }
172
+ void visitDecl (Decl *decl) {
173
+ llvm_unreachable (" Declarations not supported" );
174
+ }
185
175
186
- // / Coerce a closure whose body produces \c Never into one that does not
187
- // / return its result.
188
- static void coerceClosureExprFromNever (
189
- Solution &solution, ClosureExpr *closure) {
190
- auto &cs = solution.getConstraintSystem ();
176
+ ASTNode visitBraceStmt (BraceStmt *braceStmt) {
177
+ for (auto &node : braceStmt->getElements ()) {
178
+ if (auto expr = node.dyn_cast <Expr *>()) {
179
+ // Rewrite the expression.
180
+ if (auto rewrittenExpr = rewriteExpr (expr))
181
+ node = expr;
182
+ else
183
+ hadError = true ;
184
+ } else if (auto stmt = node.dyn_cast <Stmt *>()) {
185
+ node = visit (stmt);
186
+ } else {
187
+ visitDecl (node.get <Decl *>());
188
+ }
189
+ }
190
+
191
+ return braceStmt;
192
+ }
191
193
192
- // Re-write the single-expression closure to drop the 'return'.
193
- assert (closure->hasSingleExpressionBody ());
194
+ ASTNode visitReturnStmt (ReturnStmt *returnStmt) {
195
+ auto resultExpr = returnStmt->getResult ();
196
+ if (!resultExpr)
197
+ return returnStmt;
194
198
195
- // A single-expression body contains a single return statement
196
- // prior to this transformation.
197
- auto member = closure->getBody ()->getFirstElement ();
199
+ enum {
200
+ convertToResult,
201
+ coerceToVoid,
202
+ coerceFromNever,
203
+ } mode;
198
204
199
- if (member.is <Stmt *>()) {
200
- auto returnStmt = cast<ReturnStmt>(member.get <Stmt *>());
201
- auto singleExpr = returnStmt->getResult ();
205
+ auto resultExprType =
206
+ solution.simplifyType (solution.getType (resultExpr))->getRValueType ();
207
+ // A closure with a non-void return expression can coerce to a closure
208
+ // that returns Void.
209
+ if (resultType->isVoid () && !resultExprType->isVoid ()) {
210
+ mode = coerceToVoid;
202
211
203
- solution.setExprTypes (singleExpr);
204
- TypeChecker::checkIgnoredExpr (singleExpr);
212
+ // A single-expression closure with a Never expression type
213
+ // coerces to any other function type.
214
+ } else if (isSingleExpression && resultExprType->isUninhabited ()) {
215
+ mode = coerceFromNever;
216
+
217
+ // Normal rule is to coerce to the return expression to the closure type.
218
+ } else {
219
+ mode = convertToResult;
220
+ }
205
221
206
- SmallVector<ASTNode, 1 > elements;
207
- elements.push_back (singleExpr);
222
+ SolutionApplicationTarget resultTarget (
223
+ resultExpr, closure,
224
+ mode == convertToResult ? CTP_ReturnStmt : CTP_Unused,
225
+ mode == convertToResult ? resultType : Type (),
226
+ /* isDiscarded=*/ false );
227
+ if (auto newResultTarget = rewriteTarget (resultTarget))
228
+ resultExpr = newResultTarget->getAsExpr ();
229
+
230
+ switch (mode) {
231
+ case convertToResult:
232
+ // Record the coerced expression.
233
+ returnStmt->setResult (resultExpr);
234
+ return returnStmt;
235
+
236
+ case coerceToVoid: {
237
+ // Evaluate the expression, then produce a return statement that
238
+ // returns nothing.
239
+ TypeChecker::checkIgnoredExpr (resultExpr);
240
+ auto &ctx = solution.getConstraintSystem ().getASTContext ();
241
+ auto newReturnStmt =
242
+ new (ctx) ReturnStmt (
243
+ returnStmt->getStartLoc (), nullptr , /* implicit=*/ true );
244
+ ASTNode elements[2 ] = { resultExpr, newReturnStmt };
245
+ return BraceStmt::create (ctx, returnStmt->getStartLoc (),
246
+ elements, returnStmt->getEndLoc (),
247
+ /* implicit*/ true );
248
+ }
208
249
209
- auto braceStmt =
210
- BraceStmt::create (cs.getASTContext (), closure->getStartLoc (),
211
- elements, closure->getEndLoc (),
212
- /* implicit*/ true );
250
+ case coerceFromNever:
251
+ // Replace the return statement with its expression, so that the
252
+ // expression is evaluated directly. This only works because coercion
253
+ // from never is limited to single-expression closures.
254
+ return resultExpr;
255
+ }
213
256
214
- closure->setImplicit ();
215
- closure->setBody (braceStmt, /* isSingleExpression*/ true );
257
+ return returnStmt;
216
258
}
259
+
260
+ #define UNSUPPORTED_STMT (STMT ) ASTNode visit##STMT##Stmt(STMT##Stmt *) { \
261
+ llvm_unreachable (" Unsupported statement kind " #STMT); \
262
+ }
263
+ UNSUPPORTED_STMT (Yield)
264
+ UNSUPPORTED_STMT(Defer)
265
+ UNSUPPORTED_STMT(If)
266
+ UNSUPPORTED_STMT(Guard)
267
+ UNSUPPORTED_STMT(While)
268
+ UNSUPPORTED_STMT(Do)
269
+ UNSUPPORTED_STMT(DoCatch)
270
+ UNSUPPORTED_STMT(RepeatWhile)
271
+ UNSUPPORTED_STMT(ForEach)
272
+ UNSUPPORTED_STMT(Switch)
273
+ UNSUPPORTED_STMT(Case)
274
+ UNSUPPORTED_STMT(Break)
275
+ UNSUPPORTED_STMT(Continue)
276
+ UNSUPPORTED_STMT(Fallthrough)
277
+ UNSUPPORTED_STMT(Fail)
278
+ UNSUPPORTED_STMT(Throw)
279
+ UNSUPPORTED_STMT(PoundAssert)
280
+ #undef UNSUPPORTED_STMT
281
+
282
+ };
283
+
217
284
}
218
285
219
286
SolutionApplicationToFunctionResult ConstraintSystem::applySolution (
220
287
Solution &solution, AnyFunctionRef fn,
221
288
DeclContext *¤tDC,
222
- std::function<
223
- Optional<SolutionApplicationTarget> (SolutionApplicationTarget)>
224
- rewriteTarget) {
289
+ RewriteTargetFn rewriteTarget) {
225
290
auto &cs = solution.getConstraintSystem ();
226
291
auto closure = dyn_cast_or_null<ClosureExpr>(fn.getAbstractClosureExpr ());
227
292
FunctionType *closureFnType = nullptr ;
@@ -274,41 +339,9 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution(
274
339
275
340
// If there is a single-expression body, transform that body now.
276
341
if (fn.hasSingleExpressionBody ()) {
277
- // Rewrite the body.
278
- SolutionApplicationTarget originalBody (
279
- fn.getSingleExpressionBody (), fn.getAsDeclContext (), CTP_Unused,
280
- Type (), /* isDiscarded=*/ false );
281
- auto rewrittenBody = rewriteTarget (originalBody);
282
- if (!rewrittenBody)
283
- return SolutionApplicationToFunctionResult::Failure;
284
-
285
- auto body = rewrittenBody->getAsExpr ();
286
- fn.setSingleExpressionBody (body);
287
-
288
- // Closures with a single-expression body have special rules regarding
289
- // Void and Never returns. Handle them now.
290
- if (closure && closure->hasSingleExpressionBody ()) {
291
- auto bodyType = body->getType ();
292
-
293
- // A single-expression closure with a non-Void expression type
294
- // coerces to a Void-returning function type.
295
- if (closureFnType->getResult ()->isVoid () && !bodyType->isVoid ()) {
296
- coerceClosureExprToVoid (solution, closure);
297
- // A single-expression closure with a Never expression type
298
- // coerces to any other function type.
299
- } else if (bodyType->isUninhabited ()) {
300
- coerceClosureExprFromNever (solution, closure);
301
- } else {
302
- body = solution.coerceToType (body, closureFnType->getResult (),
303
- cs.getConstraintLocator (
304
- closure,
305
- ConstraintLocator::ClosureResult));
306
- if (!body)
307
- return SolutionApplicationToFunctionResult::Failure;
308
-
309
- closure->setSingleExpressionBody (body);
310
- }
311
- }
342
+ ClosureConstraintApplication application (
343
+ solution, closure, closureFnType->getResult (), rewriteTarget);
344
+ application.visit (fn.getBody ());
312
345
313
346
return SolutionApplicationToFunctionResult::Success;
314
347
}
@@ -317,4 +350,3 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution(
317
350
solution.setExprTypes (closure);
318
351
return SolutionApplicationToFunctionResult::Delay;
319
352
}
320
-
0 commit comments