Files
swift-mirror/test/expr/closure/closures_swift6.swift

321 lines
11 KiB
Swift

// RUN: %target-typecheck-verify-swift -swift-version 6
// REQUIRES: asserts
func doStuff(_ fn : @escaping () -> Int) {}
func doVoidStuff(_ fn : @escaping () -> ()) {}
func doVoidStuffNonEscaping(_ fn: () -> ()) {}
class ExplicitSelfRequiredTest {
var x = 42
func method() -> Int {
doVoidStuff({ doStuff({ x+1 })}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{28-28= [self] in}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}}
return 42
}
func weakSelfError() {
doVoidStuff({ [weak self] in x += 1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
doVoidStuffNonEscaping({ [weak self] in x += 1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
doStuff({ [weak self] in x+1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
doVoidStuff({ [weak self] in _ = method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
doVoidStuffNonEscaping({ [weak self] in _ = method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
doStuff({ [weak self] in method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
}
}
// https://github.com/apple/swift/issues/56501
class C_56501 {
func operation() {}
func test1() {
doVoidStuff { [self] in
operation()
}
}
func test2() {
doVoidStuff { [self] in
doVoidStuff {
// expected-error@+3 {{call to method 'operation' in closure requires explicit use of 'self'}}
// expected-note@-2 {{capture 'self' explicitly to enable implicit 'self' in this closure}}
// expected-note@+1 {{reference 'self.' explicitly}}
operation()
}
}
}
func test3() {
doVoidStuff { [self] in
doVoidStuff { [self] in
operation()
}
}
}
func test4() {
doVoidStuff { [self] in
doVoidStuff {
self.operation()
}
}
}
func test5() {
doVoidStuff { [self] in
doVoidStuffNonEscaping {
operation()
}
}
}
func test6() {
doVoidStuff { [self] in
doVoidStuff { [self] in
doVoidStuff {
// expected-error@+3 {{call to method 'operation' in closure requires explicit use of 'self'}}
// expected-note@-2 {{capture 'self' explicitly to enable implicit 'self' in this closure}}
// expected-note@+1 {{reference 'self.' explicitly}}
operation()
}
}
}
}
}
public class TestImplicitSelfForWeakSelfCapture {
static let staticOptional: TestImplicitSelfForWeakSelfCapture? = .init()
func method() { }
private init() {
doVoidStuff { [weak self] in
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
guard let self = self else { return }
method()
}
doVoidStuff { [weak self] in
guard let self else { return }
method()
}
doVoidStuff { [weak self] in
if let self = self {
method()
}
if let self {
method()
}
}
doVoidStuff { [weak self] in
guard let self = self else { return }
doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}}
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}}
}
}
doVoidStuff { [weak self] in
guard let self = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
doVoidStuffNonEscaping { [weak self] in
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
guard let self = self else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
if let self = self {
method()
}
}
doVoidStuff { [weak self] in
let `self`: TestImplicitSelfForWeakSelfCapture? = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional
guard let self = self else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
doVoidStuffNonEscaping { [weak self] in
let `self`: TestImplicitSelfForWeakSelfCapture? = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional
guard let self = self else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
doVoidStuffNonEscaping { [weak self] in
guard let self = self else { return }
doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}}
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}}
}
}
doVoidStuffNonEscaping { [weak self] in
guard let self = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
doVoidStuff { [weak self] in
func innerFunction1() {
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
self?.method()
}
guard let self else { return }
func innerFunction2() {
method()
self.method()
}
}
doVoidStuffNonEscaping { [weak self] in
func innerFunction1() {
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
self?.method()
}
guard let self else { return }
func innerFunction2() {
method()
self.method()
}
}
}
}
class NoImplicitSelfInInnerClass {
func method() { }
private init() { // expected-note {{'self' declared here}} expected-note {{'self' declared here}}
doVoidStuff {
class InnerType { // expected-note {{type declared here}}
func functionInsideInnerType() {
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
}
}
}
doVoidStuff { [weak self] in
guard let self else { return }
method()
class InnerType { // expected-note {{type declared here}}
func functionInsideInnerType() {
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
}
}
}
}
func foo(condition: Bool) {
doVoidStuff { [weak self] in
guard condition, let self else { return }
method()
}
doVoidStuff { [weak self] in
guard let self, condition else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard condition, let self else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard let self, condition else { return }
method()
}
}
func foo(optionalCondition: Bool?) {
doVoidStuff { [weak self] in
guard let optionalCondition, optionalCondition, let self else { return }
method()
}
doVoidStuff { [weak self] in
guard let self, let optionalCondition, optionalCondition else { return }
method()
}
doVoidStuff { [weak self] in
guard let optionalCondition, let self, optionalCondition else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard let optionalCondition, optionalCondition, let self else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard let self, let optionalCondition, optionalCondition else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard let optionalCondition, let self, optionalCondition else { return }
method()
}
}
func foo() {
doVoidStuff { [weak self] in
guard #available(SwiftStdlib 5.8, *), let self else { return }
method()
}
doVoidStuff { [weak self] in
guard let self, #available(SwiftStdlib 5.8, *) else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard #available(SwiftStdlib 5.8, *), let self else { return }
method()
}
doVoidStuffNonEscaping { [weak self] in
guard let self, #available(SwiftStdlib 5.8, *) else { return }
method()
}
}
}
public class TestRebindingSelfIsDisallowed {
let count: Void = ()
private init() {
doVoidStuff {
let `self` = "self shouldn't become a string"
let _: Int = count // expected-error{{cannot convert value of type 'Void' to specified type 'Int'}}
}
doVoidStuffNonEscaping {
let `self` = "self shouldn't become a string"
let _: Int = count // expected-error{{cannot convert value of type 'Void' to specified type 'Int'}}
}
doVoidStuff { [weak self] in
let `self` = "self shouldn't become a string"
let _: Int = count // expected-error{{reference to property 'count' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
doVoidStuffNonEscaping { [weak self] in
let `self` = "self shouldn't become a string"
let _: Int = count // expected-error{{reference to property 'count' in closure requires explicit use of 'self' to make capture semantics explicit}}
}
}
func method() {
let `self` = "self shouldn't become a string"
let _: Int = count // expected-error{{cannot convert value of type 'Void' to specified type 'Int'}}
}
}