Skip to content

Commit b0719f0

Browse files
authored
Merge pull request #34506 from slavapestov/var-allows-non-escaping-to-escape
SIL: Look through SILBoxType when checking for invalid non-escaping function value captures
2 parents d2fb6ac + 2d93585 commit b0719f0

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

lib/SILOptimizer/Mandatory/DiagnoseInvalidEscapingCaptures.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,22 @@ static void diagnoseCaptureLoc(ASTContext &Context, DeclContext *DC,
289289
}
290290
}
291291

292+
static bool isNonEscapingFunctionValue(SILValue value) {
293+
auto type = value->getType().getASTType();
294+
295+
// Look through box types to handle mutable 'var' bindings.
296+
if (auto boxType = dyn_cast<SILBoxType>(type)) {
297+
for (auto field : boxType->getLayout()->getFields()) {
298+
if (field.getLoweredType()->isNoEscape())
299+
return true;
300+
}
301+
302+
return false;
303+
}
304+
305+
return type->isNoEscape();
306+
}
307+
292308
// Diagnose this partial_apply if it captures a non-escaping value and has
293309
// an escaping use.
294310
static void checkPartialApply(ASTContext &Context, DeclContext *DC,
@@ -314,9 +330,8 @@ static void checkPartialApply(ASTContext &Context, DeclContext *DC,
314330

315331
// Captures of noescape function types or tuples containing noescape
316332
// function types cannot escape.
317-
if (value->getType().getASTType()->isNoEscape()) {
333+
if (isNonEscapingFunctionValue(value))
318334
noEscapeCaptures.push_back(&oper);
319-
}
320335
}
321336

322337
// A partial_apply without non-escaping captures is always valid.
@@ -416,7 +431,7 @@ static void checkPartialApply(ASTContext &Context, DeclContext *DC,
416431
static void checkApply(ASTContext &Context, FullApplySite site) {
417432
auto isNoEscapeParam = [&](SILValue value) -> const ParamDecl * {
418433
// If the value is an escaping, do not enforce any restrictions.
419-
if (!value->getType().getASTType()->isNoEscape())
434+
if (!isNonEscapingFunctionValue(value))
420435
return nullptr;
421436

422437
// If the value is not a function parameter, do not enforce any restrictions.

test/SILOptimizer/invalid_escaping_captures.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,12 @@ struct S {
247247
// expected-note@-2 {{pass a copy of 'self'}}
248248
}
249249
}
250+
251+
// Test that we look through the SILBoxType used for a 'var' binding
252+
func badNoEscapeCaptureThroughVar(_ fn: () -> ()) {
253+
var myFunc = fn // expected-warning {{never mutated}} // expected-note {{captured here}}
254+
255+
takesEscaping { // expected-error {{escaping closure captures non-escaping value}}
256+
myFunc()
257+
}
258+
}

0 commit comments

Comments
 (0)