Skip to content

Commit bc54bc6

Browse files
authored
Revert "[TypeChecker] SE-0326: Enable multi-statement closure inference by default"
1 parent e7120a6 commit bc54bc6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+247
-480
lines changed

include/swift/Basic/LangOptions.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ namespace swift {
688688

689689
/// Enable experimental support for type inference through multi-statement
690690
/// closures.
691-
bool EnableMultiStatementClosureInference = true;
691+
bool EnableMultiStatementClosureInference = false;
692692

693693
/// See \ref FrontendOptions.PrintFullConvention
694694
bool PrintFullConvention = false;

include/swift/Sema/CSBindings.h

-8
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,6 @@ class BindingSet {
338338

339339
TypeVariableType *getTypeVariable() const { return Info.TypeVar; }
340340

341-
/// Check whether this binding set belongs to a type variable
342-
/// that represents a result type of a closure.
343-
bool forClosureResult() const;
344-
345-
/// Check whether this binding set belongs to a type variable
346-
/// that represents a generic parameter.
347-
bool forGenericParameter() const;
348-
349341
bool canBeNil() const;
350342

351343
/// If this type variable doesn't have any viable bindings, or

include/swift/Sema/CSFix.h

-4
Original file line numberDiff line numberDiff line change
@@ -2305,10 +2305,6 @@ class SpecifyClosureParameterType final : public ConstraintFix {
23052305

23062306
bool diagnose(const Solution &solution, bool asNote = false) const override;
23072307

2308-
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
2309-
return diagnose(*commonFixes.front().first);
2310-
}
2311-
23122308
static SpecifyClosureParameterType *create(ConstraintSystem &cs,
23132309
ConstraintLocator *locator);
23142310

include/swift/Sema/Constraint.h

+3-12
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
442442
ASTNode Element;
443443
/// Contextual information associated with the element (if any).
444444
ContextualTypeInfo Context;
445-
/// Identifies whether result of this node is unused.
446-
bool IsDiscarded;
447445
} ClosureElement;
448446
};
449447

@@ -497,7 +495,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
497495
SmallPtrSetImpl<TypeVariableType *> &typeVars);
498496

499497
/// Construct a closure body element constraint.
500-
Constraint(ASTNode node, ContextualTypeInfo context, bool isDiscarded,
498+
Constraint(ASTNode node, ContextualTypeInfo context,
501499
ConstraintLocator *locator,
502500
SmallPtrSetImpl<TypeVariableType *> &typeVars);
503501

@@ -587,14 +585,12 @@ class Constraint final : public llvm::ilist_node<Constraint>,
587585

588586
static Constraint *createClosureBodyElement(ConstraintSystem &cs,
589587
ASTNode node,
590-
ConstraintLocator *locator,
591-
bool isDiscarded = false);
588+
ConstraintLocator *locator);
592589

593590
static Constraint *createClosureBodyElement(ConstraintSystem &cs,
594591
ASTNode node,
595592
ContextualTypeInfo context,
596-
ConstraintLocator *locator,
597-
bool isDiscarded = false);
593+
ConstraintLocator *locator);
598594

599595
/// Determine the kind of constraint.
600596
ConstraintKind getKind() const { return Kind; }
@@ -861,11 +857,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
861857
return ClosureElement.Context;
862858
}
863859

864-
bool isDiscardedElement() const {
865-
assert(Kind == ConstraintKind::ClosureBodyElement);
866-
return ClosureElement.IsDiscarded;
867-
}
868-
869860
/// For an applicable function constraint, retrieve the trailing closure
870861
/// matching rule.
871862
Optional<TrailingClosureMatching> getTrailingClosureMatching() const;

include/swift/Sema/ConstraintSystem.h

+15-14
Original file line numberDiff line numberDiff line change
@@ -4854,8 +4854,8 @@ class ConstraintSystem {
48544854
/// Simplify a closure body element constraint by generating required
48554855
/// constraints to represent the given element in constraint system.
48564856
SolutionKind simplifyClosureBodyElementConstraint(
4857-
ASTNode element, ContextualTypeInfo context, bool isDiscarded,
4858-
TypeMatchOptions flags, ConstraintLocatorBuilder locator);
4857+
ASTNode element, ContextualTypeInfo context, TypeMatchOptions flags,
4858+
ConstraintLocatorBuilder locator);
48594859

48604860
public: // FIXME: Public for use by static functions.
48614861
/// Simplify a conversion constraint with a fix applied to it.
@@ -5014,8 +5014,7 @@ class ConstraintSystem {
50145014
/// \param replaceInvalidRefsWithErrors Indicates whether it's allowed
50155015
/// to replace any discovered invalid member references with `ErrorExpr`.
50165016
static bool preCheckExpression(Expr *&expr, DeclContext *dc,
5017-
bool replaceInvalidRefsWithErrors,
5018-
bool leaveClosureBodiesUnchecked);
5017+
bool replaceInvalidRefsWithErrors);
50195018

50205019
/// Solve the system of constraints generated from provided target.
50215020
///
@@ -5246,16 +5245,6 @@ class ConstraintSystem {
52465245
/// imported from C/ObjectiveC.
52475246
bool isArgumentOfImportedDecl(ConstraintLocatorBuilder locator);
52485247

5249-
/// Check whether given closure should participate in inference e.g.
5250-
/// if it's a single-expression closure - it always does, but
5251-
/// multi-statement closures require special flags.
5252-
bool participatesInInference(ClosureExpr *closure) const;
5253-
5254-
/// Visit each subexpression that will be part of the constraint system
5255-
/// of the given expression, including those in closure bodies that will be
5256-
/// part of the constraint system.
5257-
void forEachExpr(Expr *expr, llvm::function_ref<Expr *(Expr *)> callback);
5258-
52595248
SWIFT_DEBUG_DUMP;
52605249
SWIFT_DEBUG_DUMPER(dump(Expr *));
52615250

@@ -6080,6 +6069,18 @@ BraceStmt *applyResultBuilderTransform(
60806069
constraints::SolutionApplicationTarget)>
60816070
rewriteTarget);
60826071

6072+
/// Determine whether the given closure expression should be type-checked
6073+
/// within the context of its enclosing expression. Otherwise, it will be
6074+
/// separately type-checked once its enclosing expression has determined all
6075+
/// of the parameter and result types without looking at the body.
6076+
bool shouldTypeCheckInEnclosingExpression(ClosureExpr *expr);
6077+
6078+
/// Visit each subexpression that will be part of the constraint system
6079+
/// of the given expression, including those in closure bodies that will be
6080+
/// part of the constraint system.
6081+
void forEachExprInConstraintSystem(
6082+
Expr *expr, llvm::function_ref<Expr *(Expr *)> callback);
6083+
60836084
/// Whether the given parameter requires an argument.
60846085
bool parameterRequiresArgument(
60856086
ArrayRef<AnyFunctionType::Param> params,

include/swift/Sema/IDETypeChecking.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ namespace swift {
4747
struct PrintOptions;
4848

4949
/// Typecheck binding initializer at \p bindingIndex.
50-
void typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex,
51-
bool leaveClosureBodiesUnchecked);
50+
void typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex);
5251

5352
/// Check if T1 is convertible to T2.
5453
///

lib/IDE/ExprContextAnalysis.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) {
9898
[](VarDecl *VD) { (void)VD->getInterfaceType(); });
9999
if (PBD->getInit(i)) {
100100
if (!PBD->isInitializerChecked(i))
101-
typeCheckPatternBinding(PBD, i,
102-
/*LeaveClosureBodyUnchecked=*/true);
101+
typeCheckPatternBinding(PBD, i);
103102
}
104103
}
105104
} else if (auto *defaultArg = dyn_cast<DefaultArgumentInitializer>(DC)) {

lib/Sema/BuilderTransform.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1932,9 +1932,7 @@ class PreCheckResultBuilderApplication : public ASTWalker {
19321932
DiagnosticTransaction transaction(diagEngine);
19331933

19341934
HasError |= ConstraintSystem::preCheckExpression(
1935-
E, DC, /*replaceInvalidRefsWithErrors=*/true,
1936-
/*leaveClosureBodiesUnchecked=*/false);
1937-
1935+
E, DC, /*replaceInvalidRefsWithErrors=*/true);
19381936
HasError |= transaction.hasErrors();
19391937

19401938
if (!HasError)

lib/Sema/CSApply.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -4056,7 +4056,8 @@ namespace {
40564056
if (expr->isLiteralInit()) {
40574057
auto *literalInit = expr->getSubExpr();
40584058
if (auto *call = dyn_cast<CallExpr>(literalInit)) {
4059-
cs.forEachExpr(call->getFn(), [&](Expr *subExpr) -> Expr * {
4059+
forEachExprInConstraintSystem(call->getFn(),
4060+
[&](Expr *subExpr) -> Expr * {
40604061
auto *TE = dyn_cast<TypeExpr>(subExpr);
40614062
if (!TE)
40624063
return subExpr;

lib/Sema/CSBindings.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,6 @@ using namespace swift;
2525
using namespace constraints;
2626
using namespace inference;
2727

28-
bool BindingSet::forClosureResult() const {
29-
return Info.TypeVar->getImpl().isClosureResultType();
30-
}
31-
32-
bool BindingSet::forGenericParameter() const {
33-
return bool(Info.TypeVar->getImpl().getGenericParameter());
34-
}
35-
3628
bool BindingSet::canBeNil() const {
3729
auto &ctx = CS.getASTContext();
3830
return Literals.count(

lib/Sema/CSClosure.cpp

+27-55
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//
1717
//===----------------------------------------------------------------------===//
1818

19-
#include "MiscDiagnostics.h"
2019
#include "TypeChecker.h"
2120
#include "swift/Sema/ConstraintSystem.h"
2221

@@ -163,8 +162,8 @@ static bool isViableElement(ASTNode element) {
163162
return true;
164163
}
165164

166-
using ElementInfo = std::tuple<ASTNode, ContextualTypeInfo,
167-
/*isDiscarded=*/bool, ConstraintLocator *>;
165+
using ElementInfo =
166+
std::tuple<ASTNode, ContextualTypeInfo, ConstraintLocator *>;
168167

169168
static void createConjunction(ConstraintSystem &cs,
170169
ArrayRef<ElementInfo> elements,
@@ -191,8 +190,7 @@ static void createConjunction(ConstraintSystem &cs,
191190
for (const auto &entry : elements) {
192191
ASTNode element = std::get<0>(entry);
193192
ContextualTypeInfo context = std::get<1>(entry);
194-
bool isDiscarded = std::get<2>(entry);
195-
ConstraintLocator *elementLoc = std::get<3>(entry);
193+
ConstraintLocator *elementLoc = std::get<2>(entry);
196194

197195
if (!isViableElement(element))
198196
continue;
@@ -203,8 +201,8 @@ static void createConjunction(ConstraintSystem &cs,
203201
if (isIsolated)
204202
element.walk(paramCollector);
205203

206-
constraints.push_back(Constraint::createClosureBodyElement(
207-
cs, element, context, elementLoc, isDiscarded));
204+
constraints.push_back(
205+
Constraint::createClosureBodyElement(cs, element, context, elementLoc));
208206
}
209207

210208
// It's possible that there are no viable elements in the body,
@@ -222,9 +220,8 @@ static void createConjunction(ConstraintSystem &cs,
222220
}
223221

224222
ElementInfo makeElement(ASTNode node, ConstraintLocator *locator,
225-
ContextualTypeInfo context = ContextualTypeInfo(),
226-
bool isDiscarded = false) {
227-
return std::make_tuple(node, context, isDiscarded, locator);
223+
ContextualTypeInfo context = ContextualTypeInfo()) {
224+
return std::make_tuple(node, context, locator);
228225
}
229226

230227
static ProtocolDecl *getSequenceProtocol(ASTContext &ctx, SourceLoc loc,
@@ -754,8 +751,6 @@ class ClosureConstraintGenerator
754751

755752
void visitBraceStmt(BraceStmt *braceStmt) {
756753
if (isSupportedMultiStatementClosure()) {
757-
auto &ctx = cs.getASTContext();
758-
759754
if (isChildOf(StmtKind::Case)) {
760755
auto *caseStmt = cast<CaseStmt>(
761756
locator->castLastElementTo<LocatorPathElt::ClosureBodyElement>()
@@ -770,15 +765,10 @@ class ClosureConstraintGenerator
770765

771766
SmallVector<ElementInfo, 4> elements;
772767
for (auto element : braceStmt->getElements()) {
773-
bool isDiscarded =
774-
element.is<Expr *>() &&
775-
(!ctx.LangOpts.Playground && !ctx.LangOpts.DebuggerSupport);
776-
777768
elements.push_back(makeElement(
778769
element,
779770
cs.getConstraintLocator(
780-
locator, LocatorPathElt::ClosureBodyElement(element)),
781-
/*contextualInfo=*/{}, isDiscarded));
771+
locator, LocatorPathElt::ClosureBodyElement(element))));
782772
}
783773

784774
createConjunction(cs, elements, locator);
@@ -855,7 +845,7 @@ class ClosureConstraintGenerator
855845

856846
bool isSupportedMultiStatementClosure() const {
857847
return !closure->hasSingleExpressionBody() &&
858-
cs.participatesInInference(closure);
848+
shouldTypeCheckInEnclosingExpression(closure);
859849
}
860850

861851
#define UNSUPPORTED_STMT(STMT) void visit##STMT##Stmt(STMT##Stmt *) { \
@@ -886,7 +876,7 @@ class ClosureConstraintGenerator
886876
bool ConstraintSystem::generateConstraints(ClosureExpr *closure) {
887877
auto &ctx = closure->getASTContext();
888878

889-
if (participatesInInference(closure)) {
879+
if (shouldTypeCheckInEnclosingExpression(closure)) {
890880
ClosureConstraintGenerator generator(*this, closure,
891881
getConstraintLocator(closure));
892882
generator.visit(closure->getBody());
@@ -935,22 +925,28 @@ bool isConditionOfStmt(ConstraintLocatorBuilder locator) {
935925

936926
ConstraintSystem::SolutionKind
937927
ConstraintSystem::simplifyClosureBodyElementConstraint(
938-
ASTNode element, ContextualTypeInfo context, bool isDiscarded,
939-
TypeMatchOptions flags, ConstraintLocatorBuilder locator) {
928+
ASTNode element, ContextualTypeInfo context, TypeMatchOptions flags,
929+
ConstraintLocatorBuilder locator) {
940930
auto *closure = castToExpr<ClosureExpr>(locator.getAnchor());
941931

942932
ClosureConstraintGenerator generator(*this, closure,
943933
getConstraintLocator(locator));
944934

945935
if (auto *expr = element.dyn_cast<Expr *>()) {
946-
SolutionApplicationTarget target(expr, closure, context.purpose,
947-
context.getType(), isDiscarded);
936+
if (context.purpose != CTP_Unused) {
937+
SolutionApplicationTarget target(expr, closure, context.purpose,
938+
context.getType(),
939+
/*isDiscarded=*/false);
948940

949-
if (generateConstraints(target, FreeTypeVariableBinding::Disallow))
950-
return SolutionKind::Error;
941+
if (generateConstraints(target, FreeTypeVariableBinding::Disallow))
942+
return SolutionKind::Error;
943+
944+
setSolutionApplicationTarget(expr, target);
945+
return SolutionKind::Solved;
946+
}
951947

952-
setSolutionApplicationTarget(expr, target);
953-
return SolutionKind::Solved;
948+
if (!generateConstraints(expr, closure, /*isInputExpression=*/false))
949+
return SolutionKind::Error;
954950
} else if (auto *stmt = element.dyn_cast<Stmt *>()) {
955951
generator.visit(stmt);
956952
} else if (auto *cond = element.dyn_cast<StmtCondition *>()) {
@@ -1164,17 +1160,12 @@ class ClosureConstraintApplication
11641160

11651161
auto forEachTarget =
11661162
rewriteTarget(*cs.getSolutionApplicationTarget(forEachStmt));
1167-
11681163
if (!forEachTarget)
11691164
hadError = true;
11701165

11711166
auto body = visit(forEachStmt->getBody()).get<Stmt *>();
11721167
forEachStmt->setBody(cast<BraceStmt>(body));
11731168

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-
11781169
return forEachStmt;
11791170
}
11801171

@@ -1250,32 +1241,13 @@ class ClosureConstraintApplication
12501241
}
12511242

12521243
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-
12671244
for (auto &node : braceStmt->getElements()) {
12681245
if (auto expr = node.dyn_cast<Expr *>()) {
12691246
// Rewrite the expression.
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 {
1247+
if (auto rewrittenExpr = rewriteExpr(expr))
1248+
node = rewrittenExpr;
1249+
else
12771250
hadError = true;
1278-
}
12791251
} else if (auto stmt = node.dyn_cast<Stmt *>()) {
12801252
node = visit(stmt);
12811253
} else {

0 commit comments

Comments
 (0)