|
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