Skip to content

Commit 04bf432

Browse files
committed
SILGen: Diagnose invalid captures of top-level bindings
A method of a nominal type is not allowed to capture anything. If we did compute a capture list, clear it out to preserve downstream invariants. This can happen because not all invalid captures involving nominal types in local context can be diagnosed in Sema. In particular, we allow a method of a local type to reference a local function from an outer scope, as long as that local function does not have any (transitive) captures. Since Sema cannot validate the latter condition, it punts and allows any reference to a FuncDecl in local context. When emitting the captures in this situation, SILGen will diagnose the problem using the existing 'forward reference' logic. The diagnostic is sub-optimal -- it should talk about a reference from inside a local type, and not a 'forward reference'. But still better than crashing.
1 parent 1904960 commit 04bf432

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

lib/SIL/TypeLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,6 +2392,15 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
23922392
resultingCaptures.push_back(*selfCapture);
23932393
}
23942394

2395+
// It is an error for a member of a nominal type to have any captures
2396+
// at all. If we just clear them out here, SILGen will diagnose the
2397+
// problem.
2398+
if (fn.hasDecl()) {
2399+
auto *dc = fn.getDecl()->getDeclContext();
2400+
if (dc->isTypeContext())
2401+
resultingCaptures.clear();
2402+
}
2403+
23952404
// Cache the uniqued set of transitive captures.
23962405
CaptureInfo info{Context, resultingCaptures, capturesDynamicSelf,
23972406
capturesOpaqueValue, capturesGenericParams};

test/SILGen/nested_types_referencing_nested_functions.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-emit-silgen -module-name nested_types_referencing_nested_functions %s | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen -verify -module-name nested_types_referencing_nested_functions %s | %FileCheck %s
33

44
do {
55
func foo() { bar(2) }
@@ -32,3 +32,19 @@ do {
3232
_ = x.zim
3333
_ = x.zang as (Int) -> ()
3434
}
35+
36+
// Invalid case
37+
do {
38+
var x = 123 // expected-note {{captured value declared here}}
39+
40+
func local() {
41+
// expected-error@-1 {{closure captures 'x' before it is declared}}
42+
_ = x // expected-note {{captured here}}
43+
}
44+
45+
class Bar {
46+
func zang() {
47+
local()
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)