Skip to content

Commit ab96afa

Browse files
committed
[SILGen] Assert that captures have been computed
Before using the capture info, SILGen now asserts that it has computed, except for declarations which are not in a local context and therefore can’t have captures. This causes failures in REPL tests, but they are actual failures—there’s a bug in TypeCheckREPL.
1 parent eca51d4 commit ab96afa

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
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/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 (const CaptureInfo &captureInfo)> collectCaptures;
2140+
std::function<void (const CaptureInfo &captureInfo, DeclContext *dc)> collectCaptures;
21362141
std::function<void (AnyFunctionRef)> collectFunctionCaptures;
21372142
std::function<void (SILDeclRef)> collectConstantCaptures;
21382143

2139-
collectCaptures = [&](const CaptureInfo &captureInfo) {
2144+
collectCaptures = [&](const 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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,14 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
706706
CaptureInfo captureInfo;
707707
if (function.getAnyFunctionRef())
708708
captureInfo = SGM.M.Types.getLoweredLocalCaptures(function);
709+
else {
710+
// The expressions for these cannot capture.
711+
assert(function.kind == SILDeclRef::Kind::StoredPropertyInitializer ||
712+
function.kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer ||
713+
(function.getDecl() && !function.getDecl()->getDeclContext()->isLocalContext()));
714+
captureInfo = CaptureInfo::empty();
715+
}
716+
709717
auto interfaceType = value->getType()->mapTypeOutOfContext();
710718
emitProlog(captureInfo, params, /*selfParam=*/nullptr,
711719
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(const 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(

0 commit comments

Comments
 (0)