16
16
//
17
17
// ===----------------------------------------------------------------------===//
18
18
19
+ #include " MiscDiagnostics.h"
19
20
#include " TypeChecker.h"
20
21
#include " swift/Sema/ConstraintSystem.h"
21
22
@@ -162,8 +163,8 @@ static bool isViableElement(ASTNode element) {
162
163
return true ;
163
164
}
164
165
165
- using ElementInfo =
166
- std::tuple<ASTNode, ContextualTypeInfo , ConstraintLocator *>;
166
+ using ElementInfo = std::tuple<ASTNode, ContextualTypeInfo,
167
+ /* isDiscarded= */ bool , ConstraintLocator *>;
167
168
168
169
static void createConjunction (ConstraintSystem &cs,
169
170
ArrayRef<ElementInfo> elements,
@@ -190,7 +191,8 @@ static void createConjunction(ConstraintSystem &cs,
190
191
for (const auto &entry : elements) {
191
192
ASTNode element = std::get<0 >(entry);
192
193
ContextualTypeInfo context = std::get<1 >(entry);
193
- ConstraintLocator *elementLoc = std::get<2 >(entry);
194
+ bool isDiscarded = std::get<2 >(entry);
195
+ ConstraintLocator *elementLoc = std::get<3 >(entry);
194
196
195
197
if (!isViableElement (element))
196
198
continue ;
@@ -201,8 +203,8 @@ static void createConjunction(ConstraintSystem &cs,
201
203
if (isIsolated)
202
204
element.walk (paramCollector);
203
205
204
- constraints.push_back (
205
- Constraint::createClosureBodyElement ( cs, element, context, elementLoc));
206
+ constraints.push_back (Constraint::createClosureBodyElement (
207
+ cs, element, context, elementLoc, isDiscarded ));
206
208
}
207
209
208
210
// It's possible that there are no viable elements in the body,
@@ -220,8 +222,9 @@ static void createConjunction(ConstraintSystem &cs,
220
222
}
221
223
222
224
ElementInfo makeElement (ASTNode node, ConstraintLocator *locator,
223
- ContextualTypeInfo context = ContextualTypeInfo()) {
224
- return std::make_tuple (node, context, locator);
225
+ ContextualTypeInfo context = ContextualTypeInfo(),
226
+ bool isDiscarded = false) {
227
+ return std::make_tuple (node, context, isDiscarded, locator);
225
228
}
226
229
227
230
static ProtocolDecl *getSequenceProtocol (ASTContext &ctx, SourceLoc loc,
@@ -751,6 +754,8 @@ class ClosureConstraintGenerator
751
754
752
755
void visitBraceStmt (BraceStmt *braceStmt) {
753
756
if (isSupportedMultiStatementClosure ()) {
757
+ auto &ctx = cs.getASTContext ();
758
+
754
759
if (isChildOf (StmtKind::Case)) {
755
760
auto *caseStmt = cast<CaseStmt>(
756
761
locator->castLastElementTo <LocatorPathElt::ClosureBodyElement>()
@@ -765,10 +770,15 @@ class ClosureConstraintGenerator
765
770
766
771
SmallVector<ElementInfo, 4 > elements;
767
772
for (auto element : braceStmt->getElements ()) {
773
+ bool isDiscarded =
774
+ element.is <Expr *>() &&
775
+ (!ctx.LangOpts .Playground && !ctx.LangOpts .DebuggerSupport );
776
+
768
777
elements.push_back (makeElement (
769
778
element,
770
779
cs.getConstraintLocator (
771
- locator, LocatorPathElt::ClosureBodyElement (element))));
780
+ locator, LocatorPathElt::ClosureBodyElement (element)),
781
+ /* contextualInfo=*/ {}, isDiscarded));
772
782
}
773
783
774
784
createConjunction (cs, elements, locator);
@@ -845,7 +855,7 @@ class ClosureConstraintGenerator
845
855
846
856
bool isSupportedMultiStatementClosure () const {
847
857
return !closure->hasSingleExpressionBody () &&
848
- shouldTypeCheckInEnclosingExpression (closure);
858
+ cs. participatesInInference (closure);
849
859
}
850
860
851
861
#define UNSUPPORTED_STMT (STMT ) void visit##STMT##Stmt(STMT##Stmt *) { \
@@ -876,7 +886,7 @@ class ClosureConstraintGenerator
876
886
bool ConstraintSystem::generateConstraints (ClosureExpr *closure) {
877
887
auto &ctx = closure->getASTContext ();
878
888
879
- if (shouldTypeCheckInEnclosingExpression (closure)) {
889
+ if (participatesInInference (closure)) {
880
890
ClosureConstraintGenerator generator (*this , closure,
881
891
getConstraintLocator (closure));
882
892
generator.visit (closure->getBody ());
@@ -925,28 +935,22 @@ bool isConditionOfStmt(ConstraintLocatorBuilder locator) {
925
935
926
936
ConstraintSystem::SolutionKind
927
937
ConstraintSystem::simplifyClosureBodyElementConstraint (
928
- ASTNode element, ContextualTypeInfo context, TypeMatchOptions flags ,
929
- ConstraintLocatorBuilder locator) {
938
+ ASTNode element, ContextualTypeInfo context, bool isDiscarded ,
939
+ TypeMatchOptions flags, ConstraintLocatorBuilder locator) {
930
940
auto *closure = castToExpr<ClosureExpr>(locator.getAnchor ());
931
941
932
942
ClosureConstraintGenerator generator (*this , closure,
933
943
getConstraintLocator (locator));
934
944
935
945
if (auto *expr = element.dyn_cast <Expr *>()) {
936
- if (context.purpose != CTP_Unused) {
937
- SolutionApplicationTarget target (expr, closure, context.purpose ,
938
- context.getType (),
939
- /* isDiscarded=*/ false );
940
-
941
- if (generateConstraints (target, FreeTypeVariableBinding::Disallow))
942
- return SolutionKind::Error;
943
-
944
- setSolutionApplicationTarget (expr, target);
945
- return SolutionKind::Solved;
946
- }
946
+ SolutionApplicationTarget target (expr, closure, context.purpose ,
947
+ context.getType (), isDiscarded);
947
948
948
- if (! generateConstraints (expr, closure, /* isInputExpression= */ false ))
949
+ if (generateConstraints (target, FreeTypeVariableBinding::Disallow ))
949
950
return SolutionKind::Error;
951
+
952
+ setSolutionApplicationTarget (expr, target);
953
+ return SolutionKind::Solved;
950
954
} else if (auto *stmt = element.dyn_cast <Stmt *>()) {
951
955
generator.visit (stmt);
952
956
} else if (auto *cond = element.dyn_cast <StmtCondition *>()) {
@@ -1160,12 +1164,17 @@ class ClosureConstraintApplication
1160
1164
1161
1165
auto forEachTarget =
1162
1166
rewriteTarget (*cs.getSolutionApplicationTarget (forEachStmt));
1167
+
1163
1168
if (!forEachTarget)
1164
1169
hadError = true ;
1165
1170
1166
1171
auto body = visit (forEachStmt->getBody ()).get <Stmt *>();
1167
1172
forEachStmt->setBody (cast<BraceStmt>(body));
1168
1173
1174
+ // Check to see if the sequence expr is throwing (in async context),
1175
+ // if so require the stmt to have a `try`.
1176
+ hadError |= diagnoseUnhandledThrowsInAsyncContext (closure, forEachStmt);
1177
+
1169
1178
return forEachStmt;
1170
1179
}
1171
1180
@@ -1241,13 +1250,32 @@ class ClosureConstraintApplication
1241
1250
}
1242
1251
1243
1252
ASTNode visitBraceStmt (BraceStmt *braceStmt) {
1253
+ auto &cs = solution.getConstraintSystem ();
1254
+
1255
+ // Diagnose defer statement being last one in block.
1256
+ if (!braceStmt->empty ()) {
1257
+ if (auto stmt = braceStmt->getLastElement ().dyn_cast <Stmt *>()) {
1258
+ if (auto deferStmt = dyn_cast<DeferStmt>(stmt)) {
1259
+ auto &diags = closure->getASTContext ().Diags ;
1260
+ diags
1261
+ .diagnose (deferStmt->getStartLoc (), diag::defer_stmt_at_block_end)
1262
+ .fixItReplace (deferStmt->getStartLoc (), " do" );
1263
+ }
1264
+ }
1265
+ }
1266
+
1244
1267
for (auto &node : braceStmt->getElements ()) {
1245
1268
if (auto expr = node.dyn_cast <Expr *>()) {
1246
1269
// Rewrite the expression.
1247
- if (auto rewrittenExpr = rewriteExpr (expr))
1248
- node = rewrittenExpr;
1249
- else
1270
+ auto target = *cs.getSolutionApplicationTarget (expr);
1271
+ if (auto rewrittenTarget = rewriteTarget (target)) {
1272
+ node = rewrittenTarget->getAsExpr ();
1273
+
1274
+ if (target.isDiscardedExpr ())
1275
+ TypeChecker::checkIgnoredExpr (castToExpr (node));
1276
+ } else {
1250
1277
hadError = true ;
1278
+ }
1251
1279
} else if (auto stmt = node.dyn_cast <Stmt *>()) {
1252
1280
node = visit (stmt);
1253
1281
} else {
0 commit comments