Skip to content

Commit ecf76c8

Browse files
authored
Merge pull request swiftlang#27586 from brentdax/everything-evil
Fix keypath-as-function crasher
2 parents 008374b + f93c0ee commit ecf76c8

File tree

8 files changed

+80
-7
lines changed

8 files changed

+80
-7
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,24 @@ class TypeConverter {
972972
CaptureInfo getLoweredLocalCaptures(SILDeclRef fn);
973973
bool hasLoweredLocalCaptures(SILDeclRef fn);
974974

975+
#ifndef NDEBUG
976+
/// If \c false, \c childDC is in a context it cannot capture variables from,
977+
/// so it is expected that Sema may not have computed its \c CaptureInfo.
978+
///
979+
/// This call exists for use in assertions; do not use it to skip capture
980+
/// processing.
981+
static bool canCaptureFromParent(DeclContext *childDC) {
982+
// This call was added because Sema leaves the captures of functions that
983+
// cannot capture anything uncomputed.
984+
// TODO: Make Sema set them to CaptureInfo::empty() instead.
985+
986+
if (childDC)
987+
if (auto decl = childDC->getAsDecl())
988+
return decl->getDeclContext()->isLocalContext();
989+
return true;
990+
}
991+
#endif
992+
975993
enum class ABIDifference : uint8_t {
976994
// No ABI differences, function can be trivially bitcast to result type.
977995
Trivial,

lib/AST/CaptureInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
7878
}
7979
}
8080

81-
void CaptureInfo::dump() const {
81+
LLVM_ATTRIBUTE_USED void CaptureInfo::dump() const {
8282
print(llvm::errs());
8383
llvm::errs() << '\n';
8484
}

lib/SIL/TypeLowering.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
#include "swift/AST/NameLookup.h"
2525
#include "swift/AST/ParameterList.h"
2626
#include "swift/AST/Pattern.h"
27+
#include "swift/AST/PrettyStackTrace.h"
2728
#include "swift/AST/PropertyWrappers.h"
2829
#include "swift/AST/Types.h"
2930
#include "swift/ClangImporter/ClangModule.h"
31+
#include "swift/SIL/PrettyStackTrace.h"
3032
#include "swift/SIL/SILArgument.h"
3133
#include "swift/SIL/SILBuilder.h"
3234
#include "swift/SIL/SILModule.h"
@@ -2111,6 +2113,9 @@ TypeConverter::hasLoweredLocalCaptures(SILDeclRef fn) {
21112113

21122114
CaptureInfo
21132115
TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
2116+
PrettyStackTraceSILLocation stack("getting lowered local captures",
2117+
fn.getAsRegularLocation(), Context);
2118+
21142119
fn.isForeign = 0;
21152120
fn.isCurried = 0;
21162121
fn.isDirectReference = 0;
@@ -2132,11 +2137,14 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
21322137
DynamicSelfType *capturesDynamicSelf = nullptr;
21332138
OpaqueValueExpr *capturesOpaqueValue = nullptr;
21342139

2135-
std::function<void (CaptureInfo captureInfo)> collectCaptures;
2140+
std::function<void (CaptureInfo captureInfo, DeclContext *dc)> collectCaptures;
21362141
std::function<void (AnyFunctionRef)> collectFunctionCaptures;
21372142
std::function<void (SILDeclRef)> collectConstantCaptures;
21382143

2139-
collectCaptures = [&](CaptureInfo captureInfo) {
2144+
collectCaptures = [&](CaptureInfo captureInfo, DeclContext *dc) {
2145+
assert(captureInfo.hasBeenComputed() ||
2146+
!TypeConverter::canCaptureFromParent(dc));
2147+
21402148
if (captureInfo.hasGenericParamCaptures())
21412149
capturesGenericParams = true;
21422150
if (captureInfo.hasDynamicSelfCapture())
@@ -2263,7 +2271,9 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
22632271
if (!visitedFunctions.insert(curFn).second)
22642272
return;
22652273

2266-
collectCaptures(curFn.getCaptureInfo());
2274+
PrettyStackTraceAnyFunctionRef("lowering local captures", curFn);
2275+
auto dc = curFn.getAsDeclContext();
2276+
collectCaptures(curFn.getCaptureInfo(), dc);
22672277

22682278
// A function's captures also include its default arguments, because
22692279
// when we reference a function we don't track which default arguments
@@ -2274,17 +2284,22 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
22742284
if (auto *AFD = curFn.getAbstractFunctionDecl()) {
22752285
for (auto *P : *AFD->getParameters()) {
22762286
if (P->getDefaultValue())
2277-
collectCaptures(P->getDefaultArgumentCaptureInfo());
2287+
collectCaptures(P->getDefaultArgumentCaptureInfo(), dc);
22782288
}
22792289
}
22802290
};
22812291

22822292
collectConstantCaptures = [&](SILDeclRef curFn) {
22832293
if (curFn.isDefaultArgGenerator()) {
2294+
PrettyStackTraceSILLocation stack("lowering local captures",
2295+
fn.getAsRegularLocation(), Context);
2296+
22842297
if (auto *afd = dyn_cast<AbstractFunctionDecl>(curFn.getDecl())) {
22852298
auto *param = getParameterAt(afd, curFn.defaultArgIndex);
2286-
if (param->getDefaultValue())
2287-
collectCaptures(param->getDefaultArgumentCaptureInfo());
2299+
if (param->getDefaultValue()) {
2300+
auto dc = afd->getInnermostDeclContext();
2301+
collectCaptures(param->getDefaultArgumentCaptureInfo(), dc);
2302+
}
22882303
return;
22892304
}
22902305

lib/SILGen/SILGenFunction.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,31 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
666666
}
667667
}
668668

669+
#ifndef NDEBUG
670+
/// If \c false, \c function is either a declaration that inherently cannot
671+
/// capture variables, or it is in a context it cannot capture variables from.
672+
/// In either case, it is expected that Sema may not have computed its
673+
/// \c CaptureInfo.
674+
///
675+
/// This call exists for use in assertions; do not use it to skip capture
676+
/// processing.
677+
static bool canCaptureFromParent(SILDeclRef function) {
678+
switch (function.kind) {
679+
case SILDeclRef::Kind::StoredPropertyInitializer:
680+
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
681+
return false;
682+
683+
default:
684+
if (function.hasDecl()) {
685+
if (auto dc = dyn_cast<DeclContext>(function.getDecl())) {
686+
return TypeConverter::canCaptureFromParent(dc);
687+
}
688+
}
689+
return false;
690+
}
691+
}
692+
#endif
693+
669694
void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
670695
bool EmitProfilerIncrement) {
671696
auto *dc = function.getDecl()->getInnermostDeclContext();
@@ -706,6 +731,11 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
706731
CaptureInfo captureInfo;
707732
if (function.getAnyFunctionRef())
708733
captureInfo = SGM.M.Types.getLoweredLocalCaptures(function);
734+
else {
735+
assert(!canCaptureFromParent(function));
736+
captureInfo = CaptureInfo::empty();
737+
}
738+
709739
auto interfaceType = value->getType()->mapTypeOutOfContext();
710740
emitProlog(captureInfo, params, /*selfParam=*/nullptr,
711741
dc, interfaceType, /*throws=*/false, SourceLoc());

lib/SILGen/SILGenProlog.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
445445

446446
// Emit the capture argument variables. These are placed last because they
447447
// become the first curry level of the SIL function.
448+
assert((captureInfo.hasBeenComputed() ||
449+
!TypeConverter::canCaptureFromParent(DC)) &&
450+
"can't emit prolog of function with uncomputed captures");
448451
for (auto capture : captureInfo.getCaptures()) {
449452
if (capture.isDynamicSelfMetadata()) {
450453
auto selfMetatype = MetatypeType::get(

lib/Sema/CSApply.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4504,6 +4504,10 @@ namespace {
45044504
outerClosure->setType(outerClosureTy);
45054505
cs.cacheType(outerClosure);
45064506

4507+
// The inner closure at least will definitely have a capture.
4508+
cs.TC.ClosuresWithUncomputedCaptures.push_back(outerClosure);
4509+
cs.TC.ClosuresWithUncomputedCaptures.push_back(closure);
4510+
45074511
// let outerApply = "\( outerClosure )( \(E) )"
45084512
auto outerApply = CallExpr::createImplicit(ctx, outerClosure, {E}, {});
45094513
outerApply->setType(closureTy);

lib/Sema/TypeCheckREPL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) {
270270
BraceStmt *Body = builder.createBodyStmt(Loc, EndLoc);
271271
CE->setBody(Body, false);
272272
TC.typeCheckClosureBody(CE);
273+
TC.ClosuresWithUncomputedCaptures.push_back(CE);
273274

274275
auto *TheCall = CallExpr::createImplicit(Context, CE, { E }, { });
275276
TheCall->getArg()->setType(AnyFunctionType::composeInput(Context, args, false));
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// RUN: %target-swift-frontend %s -emit-silgen -o /dev/null
2+
let _: ([Int]) -> Int = \[Int].count

0 commit comments

Comments
 (0)