|
1 |
| -// RUN: %target-run-simple-swift(-Xfrontend -enable-copy-propagation) | %FileCheck %s |
| 1 | +// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -parse-as-library -Xfrontend -enable-copy-propagation) | %FileCheck %s |
2 | 2 |
|
| 3 | +// REQUIRES: concurrency |
3 | 4 | // REQUIRES: executable_test
|
4 | 5 |
|
5 | 6 | // =============================================================================
|
@@ -142,19 +143,79 @@ func test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction() {
|
142 | 143 | test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit("blue")
|
143 | 144 | }
|
144 | 145 |
|
| 146 | +func do_foo(_ work: () -> ()) { |
| 147 | + work() |
| 148 | +} |
| 149 | +class Fooer { |
| 150 | + __consuming func foo() { |
| 151 | + weak var weakSelf = self |
| 152 | + do_foo { |
| 153 | + weakSelf?.foo1() |
| 154 | + weakSelf?.foo2() |
| 155 | + } |
| 156 | + } |
| 157 | + func foo1() { |
| 158 | + // CHECK: Fooer foo1 |
| 159 | + print(type(of: self), #function) |
| 160 | + } |
| 161 | + func foo2() { |
| 162 | + // CHECK: Fooer foo2 |
| 163 | + print(type(of: self), #function) |
| 164 | + } |
| 165 | +} |
| 166 | + |
| 167 | +func test_self_keepsObjectAliveBeyond_callTo_functionTakingClosureCapturingWeakVar() { |
| 168 | + Fooer().foo() |
| 169 | +} |
| 170 | + |
| 171 | +func do_foo_async(_ work: @escaping () -> ()) -> Task<Void, Never> { |
| 172 | + Task { |
| 173 | + work() |
| 174 | + } |
| 175 | +} |
| 176 | +class FooerAsync { |
| 177 | + var strongSelf: FooerAsync? |
| 178 | + __consuming func foo() -> Task<Void, Never> { |
| 179 | + weak var weakSelf = self |
| 180 | + strongSelf = self |
| 181 | + return do_foo_async { |
| 182 | + // At this point, strongSelf is keeping the object alive. |
| 183 | + weakSelf?.foo1() |
| 184 | + // By this point, strongSelf has been nil'd, dropping the object's retain |
| 185 | + // count to 0, deallocating the object, so weakSelf is nil. |
| 186 | + weakSelf?.foo2() |
| 187 | + } |
| 188 | + } |
| 189 | + func foo1() { |
| 190 | + // CHECK: FooerAsync foo1 |
| 191 | + print(type(of: self), #function) |
| 192 | + strongSelf = nil |
| 193 | + } |
| 194 | + func foo2() { |
| 195 | + // CHECK-NOT: FooerAsync foo2 |
| 196 | + print(type(of: self), #function) |
| 197 | + } |
| 198 | +} |
| 199 | + |
| 200 | +func test_repeatedLoadWeakSelf() -> Task<Void, Never> { |
| 201 | + FooerAsync().foo() |
| 202 | +} |
| 203 | + |
145 | 204 | // =============================================================================
|
146 | 205 | // = Tests }} =
|
147 | 206 | // =============================================================================
|
148 | 207 |
|
149 |
| -func run() { |
150 |
| - test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference() |
151 |
| - // Reenable with rdar://86271875 |
152 |
| - // test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference() |
153 |
| - test_localLet_keepsObjectAliveBeyondCallToClassWithPointer() |
154 |
| - test_localVar_keepsObjectAliveBeyondCallToClassWithPointer() |
155 |
| - test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction() |
156 |
| - test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction() |
| 208 | +@main struct Main { |
| 209 | + static func main() async { |
| 210 | + test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference() |
| 211 | + // Reenable with rdar://86271875 |
| 212 | + // test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference() |
| 213 | + test_localLet_keepsObjectAliveBeyondCallToClassWithPointer() |
| 214 | + test_localVar_keepsObjectAliveBeyondCallToClassWithPointer() |
| 215 | + test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction() |
| 216 | + test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction() |
| 217 | + |
| 218 | + test_self_keepsObjectAliveBeyond_callTo_functionTakingClosureCapturingWeakVar() |
| 219 | + await test_repeatedLoadWeakSelf().value |
| 220 | + } |
157 | 221 | }
|
158 |
| - |
159 |
| -run() |
160 |
| - |
|
0 commit comments