blob: 14ded1816956f9afbd3646b4d3a87aa92a87d768 [file] [log] [blame]
// RUN: %target-typecheck-verify-swift -swift-version 5
// Simple case.
var fn : @autoclosure () -> Int = 4 // expected-error {{'@autoclosure' may only be used on parameters}} expected-error {{cannot convert value of type 'Int' to specified type '() -> Int'}}
@autoclosure func func1() {} // expected-error {{attribute can only be applied to types, not declarations}}
func func1a(_ v1 : @autoclosure Int) {} // expected-error {{@autoclosure attribute only applies to function types}}
func func2(_ fp : @autoclosure () -> Int) { func2(4)}
func func3(fp fpx : @autoclosure () -> Int) {func3(fp: 0)}
func func4(fp : @autoclosure () -> Int) {func4(fp: 0)}
func func6(_: @autoclosure () -> Int) {func6(0)}
// autoclosure + inout doesn't make sense.
func func8(_ x: inout @autoclosure () -> Bool) -> Bool { // expected-error {{'@autoclosure' may only be used on parameters}}
}
func func9(_ x: @autoclosure (Int) -> Bool) {} // expected-error {{argument type of @autoclosure parameter must be '()'}}
func func10(_ x: @autoclosure (Int, String, Int) -> Void) {} // expected-error {{argument type of @autoclosure parameter must be '()'}}
// <rdar://problem/19707366> QoI: @autoclosure declaration change fixit
let migrate4 : (@autoclosure() -> ()) -> ()
struct SomeStruct {
@autoclosure let property : () -> Int // expected-error {{attribute can only be applied to types, not declarations}}
init() {
}
}
class BaseClass {
@autoclosure var property : () -> Int // expected-error {{attribute can only be applied to types, not declarations}}
init() {}
}
class DerivedClass {
var property : () -> Int { get {} set {} }
}
protocol P1 {
associatedtype Element
}
protocol P2 : P1 {
associatedtype Element
}
func overloadedEach<O: P1>(_ source: O, _ closure: @escaping () -> ()) {
}
func overloadedEach<P: P2>(_ source: P, _ closure: @escaping () -> ()) {
}
struct S : P2 {
typealias Element = Int
func each(_ closure: @autoclosure () -> ()) {
// expected-note@-1{{parameter 'closure' is implicitly non-escaping}}
overloadedEach(self, closure) // expected-error {{passing non-escaping parameter 'closure' to function expecting an @escaping closure}}
}
}
struct AutoclosureEscapeTest {
@autoclosure let delayed: () -> Int // expected-error {{attribute can only be applied to types, not declarations}}
}
// @autoclosure(escaping)
// expected-error @+1 {{attribute can only be applied to types, not declarations}}
func func10(@autoclosure(escaping _: () -> ()) { } // expected-error{{expected parameter name followed by ':'}}
func func11(_: @autoclosure(escaping) @noescape () -> ()) { } // expected-error{{@escaping conflicts with @noescape}}
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{28-38= @escaping}}
class Super {
func f1(_ x: @autoclosure(escaping) () -> ()) { }
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{28-38= @escaping}}
func f2(_ x: @autoclosure(escaping) () -> ()) { } // expected-note {{potential overridden instance method 'f2' here}}
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{28-38= @escaping}}
func f3(x: @autoclosure () -> ()) { }
}
class Sub : Super {
override func f1(_ x: @autoclosure(escaping)() -> ()) { }
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{37-47= @escaping }}
override func f2(_ x: @autoclosure () -> ()) { } // expected-error{{does not override any method}} // expected-note{{type does not match superclass instance method with type '(@autoclosure @escaping () -> ()) -> ()'}}
override func f3(_ x: @autoclosure(escaping) () -> ()) { } // expected-error{{does not override any method}}
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{37-47= @escaping}}
}
func func12_sink(_ x: @escaping () -> Int) { }
func func12a(_ x: @autoclosure () -> Int) {
// expected-note@-1{{parameter 'x' is implicitly non-escaping}}
func12_sink(x) // expected-error {{passing non-escaping parameter 'x' to function expecting an @escaping closure}}
}
func func12b(_ x: @autoclosure(escaping) () -> Int) {
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{31-41= @escaping}}
func12_sink(x) // ok
}
func func12c(_ x: @autoclosure @escaping () -> Int) {
func12_sink(x) // ok
}
func func12d(_ x: @escaping @autoclosure () -> Int) {
func12_sink(x) // ok
}
class TestFunc12 {
var x: Int = 5
func foo() -> Int { return 0 }
func test() {
func12a(x + foo()) // okay
func12b(x + foo())
// expected-error@-1{{reference to property 'x' in closure requires explicit 'self.' to make capture semantics explicit}} {{13-13=self.}}
// expected-error@-2{{call to method 'foo' in closure requires explicit 'self.' to make capture semantics explicit}} {{17-17=self.}}
}
}
enum AutoclosureFailableOf<T> {
case Success(@autoclosure () -> T)
case Failure
}
let _ : AutoclosureFailableOf<Int> = .Success(42)
let _ : (@autoclosure () -> ()) -> ()
let _ : (@autoclosure(escaping) () -> ()) -> ()
// expected-error@-1{{@autoclosure(escaping) has been removed; use @autoclosure @escaping instead}} {{22-32= @escaping}}
// escaping is the name of param type
let _ : (@autoclosure(escaping) -> ()) -> () // expected-error {{use of undeclared type 'escaping'}}
// Migration
// expected-error @+1 {{attribute can only be applied to types, not declarations}}
func migrateAC(@autoclosure _: () -> ()) { }
// expected-error @+1 {{attribute can only be applied to types, not declarations}}
func migrateACE(@autoclosure(escaping) _: () -> ()) { }
func takesAutoclosure(_ fn: @autoclosure () -> Int) {}
func takesThrowingAutoclosure(_: @autoclosure () throws -> Int) {}
func callAutoclosureWithNoEscape(_ fn: () -> Int) {
takesAutoclosure(1+1) // ok
}
func callAutoclosureWithNoEscape_2(_ fn: () -> Int) {
takesAutoclosure(fn()) // ok
}
func callAutoclosureWithNoEscape_3(_ fn: @autoclosure () -> Int) {
takesAutoclosure(fn()) // ok
}
// expected-error @+1 {{'@autoclosure' must not be used on variadic parameters}}
func variadicAutoclosure(_ fn: @autoclosure () -> ()...) {
for _ in fn {}
}
// rdar://41219750
// These are all arguably invalid; the autoclosure should have to be called.
// But as long as we allow them, we shouldn't crash.
func passNonThrowingToNonThrowingAC(_ fn: @autoclosure () -> Int) {
takesAutoclosure(fn) // expected-error {{add () to forward @autoclosure parameter}} {{22-22=()}}
}
func passNonThrowingToThrowingAC(_ fn: @autoclosure () -> Int) {
takesThrowingAutoclosure(fn) // expected-error {{add () to forward @autoclosure parameter}} {{30-30=()}}
}
func passThrowingToThrowingAC(_ fn: @autoclosure () throws -> Int) {
takesThrowingAutoclosure(fn) // expected-error {{add () to forward @autoclosure parameter}} {{30-30=()}}
}
func passAutoClosureToSubscriptAndMember(_ fn: @autoclosure () -> Int) {
struct S {
func bar(_: Int, _ fun: @autoclosure () -> Int) {}
subscript(_ fn: @autoclosure () -> Int) -> Int { return fn() }
static func foo(_ fn: @autoclosure () -> Int) {}
}
let s = S()
let _ = s.bar(42, fn) // expected-error {{add () to forward @autoclosure parameter}} {{23-23=()}}
let _ = s[fn] // expected-error {{add () to forward @autoclosure parameter}} {{15-15=()}}
let _ = S.foo(fn) // expected-error {{add () to forward @autoclosure parameter}} {{19-19=()}}
}
func passAutoClosureToEnumCase(_ fn: @autoclosure () -> Int) {
enum E {
case baz(@autoclosure () -> Int)
}
let _: E = .baz(42) // Ok
let _: E = .baz(fn) // expected-error {{add () to forward @autoclosure parameter}} {{21-21=()}}
}
// rdar://problem/20591571 - Various type inference problems with @autoclosure
func rdar_20591571() {
func foo(_ g: @autoclosure () -> Int) {
typealias G = ()->Int
let _ = unsafeBitCast(g, to: G.self) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
}
func id<T>(_: T) -> T {}
func same<T>(_: T, _: T) {}
func takesAnAutoclosure(_ fn: @autoclosure () -> Int, _ efn: @escaping @autoclosure () -> Int) {
// expected-note@-1 2{{parameter 'fn' is implicitly non-escaping}}
var _ = fn // expected-error {{non-escaping parameter 'fn' may only be called}}
let _ = fn // expected-error {{non-escaping parameter 'fn' may only be called}}
var _ = efn
let _ = efn
_ = id(fn) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
_ = same(fn, { 3 }) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
_ = same({ 3 }, fn) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
withoutActuallyEscaping(fn) { _ in } // Ok
withoutActuallyEscaping(fn) { (_: () -> Int) in } // Ok
}
}
// rdar://problem/30906031 - [SR-4188]: withoutActuallyEscaping doesn't accept an @autoclosure argument
func rdar_30906031(in arr: [Int], fn: @autoclosure () -> Int) -> Bool {
return withoutActuallyEscaping(fn) { escapableF in // Ok
arr.lazy.filter { $0 >= escapableF() }.isEmpty
}
}
// SR-2688
class Foo {
typealias FooClosure = () -> String
func fooFunction(closure: @autoclosure FooClosure) {} // ok
}
class Bar {
typealias BarClosure = (String) -> String
func barFunction(closure: @autoclosure BarClosure) {} // expected-error {{argument type of @autoclosure parameter must be '()'}}
}
func rdar_47586626() {
struct S {}
typealias F = () -> S
func foo(_: @autoclosure S) {} // expected-error {{@autoclosure attribute only applies to function types}}
func bar(_: @autoclosure F) {} // Ok
let s = S()
foo(s) // ok
bar(s) // ok
}
protocol P_47586626 {
typealias F = () -> Int
typealias G<T> = () -> T
func foo(_: @autoclosure F)
func bar<T>(_: @autoclosure G<T>)
}