Skip to content

Commit 9ac0dc3

Browse files
committed
SILOptimizer: Re-implement escaping capture diagnostics
The new pass is based on existing asserts in DiagnoseStaticExclusivity. They were compiled out in release builds and only checked for captures of inout parameters. This patch converts the assertions into diagnostics and adds checks for captures of non-escaping function values. Unlike the Sema-based checks that this replaces, the new code handles transitive captures from recursive local functions, which means certain invalid code that used to compile will now be rejected with an error. The new analysis also looks at the ultimate usages of a local function instead of just assuming all local functions are escaping, which fixes issues where the compiler would reject valid code. Fixes a bunch of related issues, including: - <rdar://problem/29403178> - <https://bugs.swift.org/browse/SR-8546> / <rdar://problem/43355341> - <https://bugs.swift.org/browse/SR-9043> / <rdar://problem/45511834>
1 parent 1c17ccf commit 9ac0dc3

File tree

8 files changed

+579
-208
lines changed

8 files changed

+579
-208
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ ERROR(unsupported_c_function_pointer_conversion,none,
116116
ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
117117
())
118118

119+
// Invalid escaping capture diagnostics.
120+
ERROR(escaping_inout_capture,none,
121+
"escaping closure captures 'inout' parameter %0", (Identifier))
122+
NOTE(inout_param_defined_here,none,
123+
"parameter %0 is declared 'inout'", (Identifier))
124+
ERROR(escaping_mutable_self_capture,none,
125+
"escaping closure captures mutating 'self' parameter", ())
126+
127+
ERROR(escaping_noescape_param_capture,none,
128+
"escaping closure captures non-escaping parameter %0", (Identifier))
129+
NOTE(noescape_param_defined_here,none,
130+
"parameter %0 is implicitly non-escaping", (Identifier))
131+
132+
ERROR(escaping_noescape_var_capture,none,
133+
"escaping closure captures non-escaping value", ())
134+
135+
NOTE(value_captured_here,none,"captured here", ())
136+
137+
NOTE(value_captured_transitively,none,
138+
"captured indirectly by this call", ())
139+
119140
// Definite initialization diagnostics.
120141
NOTE(variable_defined_here,none,
121142
"%select{variable|constant}0 defined here", (bool))

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ PASS(Devirtualizer, "devirtualizer",
134134
"Indirect Call Devirtualization")
135135
PASS(DiagnoseInfiniteRecursion, "diagnose-infinite-recursion",
136136
"Diagnose Infinitely-Recursive Code")
137+
PASS(DiagnoseInvalidEscapingCaptures, "diagnose-invalid-escaping-captures",
138+
"Diagnose Invalid Escaping Captures")
137139
PASS(DiagnoseStaticExclusivity, "diagnose-static-exclusivity",
138140
"Static Enforcement of Law of Exclusivity")
139141
PASS(DiagnoseUnreachable, "diagnose-unreachable",

lib/SILOptimizer/Mandatory/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ silopt_register_sources(
77
DIMemoryUseCollector.cpp
88
DataflowDiagnostics.cpp
99
DiagnoseInfiniteRecursion.cpp
10+
DiagnoseInvalidEscapingCaptures.cpp
1011
DiagnoseStaticExclusivity.cpp
1112
DiagnoseUnreachable.cpp
1213
GuaranteedARCOpts.cpp

0 commit comments

Comments
 (0)