Skip to content

[Test] Checked variable lifetimes extend self. #40744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 73 additions & 12 deletions validation-test/SILOptimizer/lexical-lifetimes.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN: %target-run-simple-swift(-Xfrontend -enable-copy-propagation) | %FileCheck %s
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -parse-as-library -Xfrontend -enable-copy-propagation) | %FileCheck %s

// REQUIRES: concurrency
// REQUIRES: executable_test

// =============================================================================
Expand Down Expand Up @@ -142,19 +143,79 @@ func test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction() {
test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit("blue")
}

func do_foo(_ work: () -> ()) {
work()
}
class Fooer {
__consuming func foo() {
weak var weakSelf = self
do_foo {
weakSelf?.foo1()
weakSelf?.foo2()
}
}
func foo1() {
// CHECK: Fooer foo1
print(type(of: self), #function)
}
func foo2() {
// CHECK: Fooer foo2
print(type(of: self), #function)
}
}

func test_self_keepsObjectAliveBeyond_callTo_functionTakingClosureCapturingWeakVar() {
Fooer().foo()
}

func do_foo_async(_ work: @escaping () -> ()) -> Task<Void, Never> {
Task {
work()
}
}
class FooerAsync {
var strongSelf: FooerAsync?
__consuming func foo() -> Task<Void, Never> {
weak var weakSelf = self
strongSelf = self
return do_foo_async {
// At this point, strongSelf is keeping the object alive.
weakSelf?.foo1()
// By this point, strongSelf has been nil'd, dropping the object's retain
// count to 0, deallocating the object, so weakSelf is nil.
weakSelf?.foo2()
}
}
func foo1() {
// CHECK: FooerAsync foo1
print(type(of: self), #function)
strongSelf = nil
}
func foo2() {
// CHECK-NOT: FooerAsync foo2
print(type(of: self), #function)
}
}

func test_repeatedLoadWeakSelf() -> Task<Void, Never> {
FooerAsync().foo()
}

// =============================================================================
// = Tests }} =
// =============================================================================

func run() {
test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference()
// Reenable with rdar://86271875
// test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference()
test_localLet_keepsObjectAliveBeyondCallToClassWithPointer()
test_localVar_keepsObjectAliveBeyondCallToClassWithPointer()
test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction()
test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction()
@main struct Main {
static func main() async {
test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference()
// Reenable with rdar://86271875
// test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference()
test_localLet_keepsObjectAliveBeyondCallToClassWithPointer()
test_localVar_keepsObjectAliveBeyondCallToClassWithPointer()
test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction()
test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction()

test_self_keepsObjectAliveBeyond_callTo_functionTakingClosureCapturingWeakVar()
await test_repeatedLoadWeakSelf().value
}
}

run()