// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-static-assert func isInt(_ value: T) -> Bool { return value is Int } func maybeGetValue(_ value: T) -> T? { return value } enum MyError: Error { case featureIsTooCool func doIt() { } } enum State { case suspended case partial(Int, Int) case finished } func random(_: Int) -> Bool { return false } func mightThrow() throws -> Bool { throw MyError.featureIsTooCool } func mapWithMoreStatements(ints: [Int], state: State) throws { let _ = try ints.map { i in guard var actualValue = maybeGetValue(i) else { return String(0) } let value = actualValue + 1 do { if isInt(i) { print(value) } else if value == 17 { print("seventeen!") } } while actualValue < 100 { actualValue += 1 } my_repeat: repeat { print("still here") if i % 7 == 0 { break my_repeat } } while random(i) defer { print("I am so done here") } for j in 0..(_ value: T, _ fn: (T) -> R) { } func testReturnWithoutExpr(i: Int) { acceptsWhateverClosure(i) { i in print(i) return } } // `withContiguousStorageIfAvailable` is overloaded, so let's make sure that // filtering works correctly. func test_overloaded_call(arr: [Int], body: (UnsafeBufferPointer) -> Void) -> Void { arr.withContiguousStorageIfAvailable { buffer in let _ = type(of: buffer) body(buffer) // ok } } // Used to wrap closure in `FunctionConversionExpr` in this case, // but now solver would just inject return expression into optional where necessary. func test_result_optional_injection() { func fn(_: () -> T?) -> [T] { [] } _ = fn { if true { return // Ok } } } let _ = { for i: Int8 in 0 ..< 20 { // Ok (pattern can inform a type of the sequence) print(i) } } func test_workaround_for_optional_void_result() { func test(_: (Int?) -> T?) {} test { guard let x = $0 else { return // Ok } print(x) } test { if $0! > 0 { return } let _ = $0 } func test_concrete(_: (Int) -> Void?) { } test_concrete { guard let x = Optional($0) else { return // Ok } print(x) } test_concrete { if $0 > 0 { return // Ok } let _ = $0 } } enum WrapperEnum where Wrapped: RawRepresentable { case known(Wrapped) static func ~= (lhs: Wrapped, rhs: WrapperEnum) -> Bool where Wrapped: Equatable { switch rhs { case .known(let wrapped): return wrapped == lhs } } } func test_custom_tilde_equals_operator_matching() { enum TildeTest : String { case test = "test" case otherTest = "" } func test(_: (WrapperEnum) -> Void) {} test { v in print(v) switch v { case .test: break // Ok although `.test` comes from `TildeTest` instead of `WrapperEnum` case .otherTest: break // Ok although `.otherTest` comes from `TildeTest` instead of `WrapperEnum` case .known(_): break // Ok - `.known` comes from `WrapperEnum` } } } // Local functions can capture variables before they are declared. func test_local_function_capturing_vars() { struct A { var cond: Bool } func test(fn: () -> T) -> T { fn() } func outer(a: A) { test { func local() { if !message.isEmpty { // Ok print(message) } message = "World" // Ok } var message = a.cond ? "hello" : "" } } } func test_test_invalid_redeclaration() { func test(_: () -> Void) { } test { let foo = 0 // expected-note {{'foo' previously declared here}} let foo = foo // expected-error {{invalid redeclaration of 'foo'}} } test { let (foo, foo) = (5, 6) // expected-error {{invalid redeclaration of 'foo'}} expected-note {{'foo' previously declared here}} } } func test_pattern_ambiguity_doesnot_crash_compiler() { enum E { case hello(result: Int) // expected-note 2 {{found this candidate}} case hello(status: Int) // expected-note 2 {{found this candidate}} } let _: (E) -> Void = { switch $0 { case .hello(_): break // expected-error {{ambiguous use of 'hello'}} } } let _: (E) -> Void = { switch $0 { case let E.hello(x): print(x) // expected-error {{ambiguous use of 'hello'}} default: break } } } func test_taps_type_checked_with_correct_decl_context() { struct Path { func contains(_: T) -> Bool where T: StringProtocol { return false } } let paths: [Path] = [] let strs: [String] = [] _ = paths.filter { path in for str in strs where path.contains("\(str).hello") { return true } return false } } // rdar://90347159 - in pattern matching context `case` should be preferred over static declarations func test_pattern_matches_only_cases() { enum ParsingError : Error { case ok(Int) case failed([Error], Int) static var ok: Int { 42 } static func failed(_: [Error], at: Any) -> Self { fatalError() } } let _: (ParsingError) -> Void = { switch $0 { case let ParsingError.failed(errors, _): print(errors) // Ok default: break } switch $0 { case let ParsingError.ok(result): print(result) // Ok default: break } } } // rdar://91225620 - type of expression is ambiguous without a type annotation in closure func test_wrapped_var_without_initializer() { @propertyWrapper struct Wrapper { private let name: String var wrappedValue: Bool { didSet {} } init(name: String) { self.wrappedValue = false self.name = name } } func fn(_: () -> Void) {} fn { @Wrapper(name: "foo") var v; } } // rdar://92366212 - crash in ConstraintSystem::getType func test_unknown_refs_in_tilde_operator() { enum E { } let _: (E) -> Void = { if case .test(unknown) = $0 { // expected-error@-1 2 {{cannot find 'unknown' in scope}} // expected-error@-2 {{type 'E' has no member 'test'}} } } } // rdar://92347054 - crash during conjunction processing func test_no_crash_with_circular_ref_due_to_error() { struct S { // expected-note {{did you mean 'S'?}} var x: Int? } func test(v: Int?, arr: [S]) -> Int { // expected-note {{did you mean 'v'?}} // There is missing `f` here which made body of the // `if` a multiple statement closure instead that uses // `next` inside. i let x = v, let next = arr.first?.x { // expected-error {{cannot find 'i' in scope}} // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} // expected-error@-2 {{'let' cannot appear nested inside another 'var' or 'let' pattern}} // expected-error@-3 {{cannot call value of non-function type 'Int?'}} print(next) return x } return 0 } } func test_diagnosing_on_missing_member_in_case() { enum E { case one } func test(_: (E) -> Void) {} test { switch $0 { case .one: break case .unknown: break // expected-error {{type 'E' has no member 'unknown'}} } } } // rdar://92757114 - fallback diagnostic when member doesn't exist in a nested closure func test_diagnose_missing_member_in_inner_closure() { struct B { static var member: any StringProtocol = "" } struct Cont { func resume(returning value: T) {} } func withCont(function: String = #function, _ body: (Cont) -> Void) -> T { fatalError() } func test(vals: [Int]?) -> [Int] { withCont { continuation in guard let vals = vals else { return continuation.resume(returning: []) } B.member.get(0, // expected-error {{value of type 'any StringProtocol' has no member 'get'}} type: "type", withinSecs: Int(60*60)) { arr in let result = arr.compactMap { $0 } return continuation.resume(returning: result) } } } } // Type finder shouldn't bring external closure result type // into the scope of an inner closure e.g. while solving // init of pattern binding `x`. func test_type_finder_doesnt_walk_into_inner_closures() { func test(fn: () -> T) -> T { fn() } _ = test { // Ok let x = test { 42 } let _ = test { test { "" } } // multi-statement let _ = test { _ = 42 return test { "" } } return x } } // rdar://94049113 - compiler accepts non-optional `guard let` in a closure func test_non_optional_guard_let_is_diagnosed() { func fn(_: (Int) -> Void) {} fn { if true { guard let v = $0 else { // expected-error {{initializer for conditional binding must have Optional type, not 'Int'}} return } print(v) } } fn { switch $0 { case (let val): fn { guard let x = val else { // expected-error {{initializer for conditional binding must have Optional type, not 'Int'}} return } print($0 + x) } default: break } } } // rdar://93796211 (issue#59035) - crash during solution application to fallthrough statement func test_fallthrough_stmt() { { var collector: [Void] = [] for _: Void in [] { switch (() as Void?, ()) { case (let a?, let b): // expected-warning@-1 {{constant 'b' inferred to have type '()', which may be unexpected}} // expected-note@-2 {{add an explicit type annotation to silence this warning}} collector.append(a) fallthrough case (nil, let b): // expected-warning@-1 {{constant 'b' inferred to have type '()', which may be unexpected}} // expected-note@-2 {{add an explicit type annotation to silence this warning}} collector.append(b) } } }() } // rdar://93061432 - No diagnostic for invalid `for-in` statement func test_missing_conformance_diagnostics_in_for_sequence() { struct Event {} struct S { struct Iterator: IteratorProtocol { typealias Element = (event: Event, timestamp: Double) mutating func next() -> Element? { return nil } } } func fn(_: () -> Void) {} func test(_ iter: inout S.Iterator) { fn { for v in iter.next() { // expected-error {{for-in loop requires 'S.Iterator.Element?' (aka 'Optional<(event: Event, timestamp: Double)>') to conform to 'Sequence'; did you mean to unwrap optional?}} _ = v.event } } fn { while let v = iter.next() { // ok _ = v.event } } } } func test_conflicting_pattern_vars() { enum E { case a(Int, String) case b(String, Int) } func fn(_: (E) -> Void) {} func fn(_: (E) -> T) {} func test(e: E) { fn { switch $0 { case .a(let x, let y), .b(let x, let y): // expected-error@-1 {{pattern variable bound to type 'String', expected type 'Int'}} // expected-error@-2 {{pattern variable bound to type 'Int', expected type 'String'}} _ = x _ = y } } fn { switch $0 { case .a(let x, let y), .b(let y, let x): // Ok _ = x _ = y } } } } // rdar://91452726 - crash in MissingMemberFailure::diagnoseInLiteralCollectionContext struct Test { struct ID { } enum E : Hashable, Equatable { case id } var arr: [(ID, E)] func test() { _ = arr.map { v in switch v { case .id: return true // expected-error {{value of tuple type '(Test.ID, Test.E)' has no member 'id'}} } } } } https://github.com/apple/swift/issues/61017 do { @propertyWrapper struct Wrapper { var wrappedValue: Int init(wrappedValue: Int) { self.wrappedValue = wrappedValue } } class Test { let bar: () -> Void = { @Wrapper var wrapped = 1 let wrapper: Wrapper = _wrapped // Ok } } } https://github.com/apple/swift/issues/61024 do { enum Baz: String { case someCase } @propertyWrapper struct Wrapper { var wrappedValue: Int let argument: String init(wrappedValue: Int, argument: String) { // expected-note 2 {{'init(wrappedValue:argument:)' declared here}} self.wrappedValue = wrappedValue self.argument = argument } } class Foo { let ok: () -> Void = { @Wrapper(argument: Baz.someCase.rawValue) var wrapped1 = 1 // Ok @Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped2 // Ok @Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped3: Int // Ok } let bad0: () -> Void = { @Wrapper var wrapped: Int // expected-error@-1 {{missing arguments for parameters 'wrappedValue', 'argument' in call}} } let bad1: () -> Void = { @Wrapper var wrapped = 0 // expected-error@-1 {{missing argument for parameter 'argument' in property wrapper initializer; add 'wrappedValue' and 'argument' arguments in '@Wrapper(...)'}} } let bad2: () -> Void = { @Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped = 0 // expected-error@-1 {{extra argument 'wrappedValue' in call}} } } } // Test to make sure that type-checker doesn't attempt the closure passed to // `.filter` before the one from `.init`, otherwise it would mean that generic // parameter of `.filter` wouldn't be inferred since it depends on result of // `.init` closure. func test_that_closures_are_attempted_in_order() { struct Test { init(_: ([Int]) -> T) {} init(_: String) {} init(_: Int, _: String = "") {} func filter(_: (T) -> Bool) {} } Test { _ = 42 return $0.map { Optional(Float($0)) } } .filter { if $0.isEmpty { // Ok return true } return false } } func test_use_of_concrete_params_in_for_condition() { struct S { var cond: Bool } func test(_: (S) -> Void) {} test { data in for i in 0...10 where !data.cond { // Ok print(i) } } } // https://github.com/apple/swift/issues/63455 func test_recursive_var_reference_in_multistatement_closure() { struct MyStruct { func someMethod() {} } func takeClosure(_ x: () -> Void) {} func test(optionalInt: Int?, themes: MyStruct?) { takeClosure { let int = optionalInt { // expected-error {{cannot call value of non-function type 'Int?'}} print(int) } } takeClosure { let theme = themes?.someMethod() { // expected-error {{extra trailing closure passed in call}} _ = theme } } takeClosure { let theme = themes?.filter({ $0 }) { // expected-error {{value of type 'MyStruct' has no member 'filter'}} _ = theme } } } } // https://github.com/apple/swift/issues/67363 func test_result_builder_in_member_chaining() { @resultBuilder struct Builder { static func buildBlock(_: T) -> Int { 42 } } struct Test { static func test(fn: () -> T) -> T { fn() } func builder(@Builder _: () -> Int) {} } Test.test { let test = Test() return test // FIXME: This call should type-check, currently closure is resolved before overload of `builder` is picked. }.builder { // expected-error {{cannot convert value of type '()' to closure result type 'Int'}} let result = "" result } }