// RUN: %target-swift-frontend -typecheck -verify -module-name main %s /** Basics *******************************************************************/ // Function types can't be rethrows right now. let r1 = {() rethrows -> Int in 0} // expected-error {{only function declarations may be marked 'rethrows'; did you mean 'throws'?}} {{14-22=throws}} let r2 : () rethrows -> Int = { 0 } // expected-error {{only function declarations may be marked 'rethrows'; did you mean 'throws'?}} {{13-21=throws}} let r3 : Optional<() rethrows -> ()> = nil // expected-error {{only function declarations may be marked 'rethrows'; did you mean 'throws'?}} {{22-30=throws}} func f1(_ f: () throws -> ()) rethrows { try f() } func f2(_ f: () -> ()) rethrows { f() } // expected-error {{'rethrows' function must take a throwing function argument}} func f3(_ f: UndeclaredFunctionType) rethrows { f() } // expected-error {{cannot find type 'UndeclaredFunctionType' in scope}} /** Protocol conformance checking ********************************************/ protocol P { func tf() throws func nf() // expected-note {{protocol requires}} func thf(_ f: () throws -> ()) throws func nhf(_ f: () throws -> ()) // expected-note 2 {{protocol requires}} func rhf(_ f: () throws -> ()) rethrows // expected-note {{protocol requires}} } struct T0 : P { // expected-error {{type 'T0' does not conform to protocol 'P'}} expected-note {{add stubs for conformance}} func tf() throws {} func nf() throws {} // expected-note {{candidate throws, but protocol does not allow it}} func thf(_ f: () throws -> ()) throws {} func nhf(_ f: () throws -> ()) throws {} // expected-note {{candidate throws, but protocol does not allow it}} func rhf(_ f: () throws -> ()) throws {} // expected-note {{candidate is not 'rethrows', but protocol requires it}} } struct T1 : P { func tf() {} func nf() {} func thf(_ f: () throws -> ()) {} func nhf(_ f: () throws -> ()) {} func rhf(_ f: () throws -> ()) {} } struct T2 : P { // expected-error {{type 'T2' does not conform to protocol 'P'}} expected-note {{add stubs for conformance}} func tf() {} func nf() {} func thf(_ f: () throws -> ()) rethrows {} func nhf(_ f: () throws -> ()) rethrows {} // expected-note {{candidate throws, but protocol does not allow it}} func rhf(_ f: () throws -> ()) rethrows {} } /** Classes ******************************************************************/ class Super { func tf() throws {} func nf() {} // expected-note {{overridden declaration is here}} func thf(_ f: () throws -> ()) throws {} func nhf(_ f: () throws -> ()) {} // expected-note 2 {{overridden declaration is here}} func rhf(_ f: () throws -> ()) rethrows {} // expected-note {{overridden declaration is here}} } class C1 : Super { override func tf() {} override func nf() {} override func thf(_ f: () throws -> ()) {} override func nhf(_ f: () throws -> ()) {} override func rhf(_ f: () throws -> ()) {} } class C2 : Super { override func tf() throws {} override func nf() throws {} // expected-error {{cannot override non-throwing instance method with throwing instance method}} override func thf(_ f: () throws -> ()) throws {} override func nhf(_ f: () throws -> ()) throws {} // expected-error {{cannot override non-throwing instance method with throwing instance method}} override func rhf(_ f: () throws -> ()) throws {} // expected-error {{override of 'rethrows' method should also be 'rethrows'}} } class C3 : Super { override func tf() {} override func nf() {} override func thf(_ f: () throws -> ()) rethrows {} override func nhf(_ f: () throws -> ()) rethrows {} // expected-error {{cannot override non-throwing instance method with throwing instance method}} override func rhf(_ f: () throws -> ()) rethrows {} } /** Semantics ****************************************************************/ @discardableResult func call(_ fn: () throws -> Int) rethrows -> Int { return try fn() } @discardableResult func callAC(_ fn: @autoclosure () throws -> Int) rethrows -> Int { return try fn() } @discardableResult func raise() throws -> Int { return 0 } @discardableResult func noraise() -> Int { return 0 } /** Global functions **/ func testCallUnhandled() { call(noraise) try call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testCallHandled() throws { call(noraise) try call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try call(raise) } func testCallACUnhandled() { callAC(noraise()) try callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{10-10=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{10-10=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{10-10=try! }} try callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testCallACHandled() throws { callAC(noraise()) try callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{10-10=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{10-10=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{10-10=try! }} try callAC(raise()) } func testForward1(_ fn: () throws -> Int) rethrows { try call(fn) } func testForward2(_ fn: () throws -> Int) rethrows { try call({ try fn() }) } /** Methods **/ struct MyStruct : MyProto { @discardableResult func call(_ fn: () throws -> Int) rethrows -> Int { return try fn() } @discardableResult func callAC(_ fn: @autoclosure () throws -> Int) rethrows -> Int { return try fn() } @discardableResult static func static_call(_ fn: () throws -> Int) rethrows -> Int { return try fn() } @discardableResult static func static_callAC(_ fn: @autoclosure () throws -> Int) rethrows -> Int { return try fn() } } func testMethodCallUnhandled(_ s: MyStruct) { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} MyStruct.static_call(noraise) try MyStruct.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} MyStruct.static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try MyStruct.static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testMethodCallHandled(_ s: MyStruct) throws { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) MyStruct.static_call(noraise) try MyStruct.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} MyStruct.static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try MyStruct.static_call(raise) } func testMethodCallACUnhandled(_ s: MyStruct) { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} MyStruct.static_callAC(noraise()) try MyStruct.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} MyStruct.static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{26-26=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{26-26=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{26-26=try! }} try MyStruct.static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testMethodCallACHandled(_ s: MyStruct) throws { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) MyStruct.static_callAC(noraise()) try MyStruct.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} MyStruct.static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{26-26=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{26-26=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{26-26=try! }} try MyStruct.static_callAC(raise()) } /** Protocol methods **/ protocol MyProto { @discardableResult func call(_ fn: () throws -> Int) rethrows -> Int @discardableResult func callAC(_ fn: @autoclosure () throws -> Int) rethrows -> Int @discardableResult static func static_call(_ fn: () throws -> Int) rethrows -> Int @discardableResult static func static_callAC(_ fn: @autoclosure () throws -> Int) rethrows -> Int } /** Existentials **/ func testProtoMethodCallUnhandled(_ s: MyProto) { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} type(of: s).static_call(noraise) try type(of: s).static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} type(of: s).static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try type(of: s).static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testProtoMethodCallHandled(_ s: MyProto) throws { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) type(of: s).static_call(noraise) try type(of: s).static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} type(of: s).static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try type(of: s).static_call(raise) } func testProtoMethodCallACUnhandled(_ s: MyProto) { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} type(of: s).static_callAC(noraise()) try type(of: s).static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} type(of: s).static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{29-29=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{29-29=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{29-29=try! }} try type(of: s).static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testProtoMethodCallACHandled(_ s: MyProto) throws { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) type(of: s).static_callAC(noraise()) try type(of: s).static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} type(of: s).static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{29-29=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{29-29=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{29-29=try! }} try type(of: s).static_callAC(raise()) } /** Generics **/ func testGenericMethodCallUnhandled(_ s: P) { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} P.static_call(noraise) try P.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} P.static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try P.static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testGenericMethodCallHandled(_ s: P) throws { s.call(noraise) try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try s.call(raise) P.static_call(noraise) try P.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}} P.static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} try P.static_call(raise) } func testGenericMethodCallACUnhandled(_ s: P) { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} P.static_callAC(noraise()) try P.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} P.static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \ // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \ // expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-3 {{did you mean to use 'try'?}} {{19-19=try }} // expected-note@-4 {{did you mean to handle error as optional value?}} {{19-19=try? }} // expected-note@-5 {{did you mean to disable error propagation?}} {{19-19=try! }} try P.static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}} } func testGenericMethodCallACHandled(_ s: P) throws { s.callAC(noraise()) try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{12-12=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{12-12=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{12-12=try! }} try s.callAC(raise()) P.static_callAC(noraise()) try P.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}} P.static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{19-19=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{19-19=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{19-19=try! }} try P.static_callAC(raise()) } /** Optional closure parameters */ func testForceUnwrappedOptionalFunctionParameter(_ f: (() throws -> Void)?) rethrows { try f!() } func testBindOptionalFunctionParameter(_ f: (() throws -> Void)?) rethrows { try f?() } func testImplicitlyUnwrappedFunctionParameter(_ f: (() throws -> Void)!) rethrows { if f != nil { try f() } } func throwingFunc() throws {} func nonThrowingFunc() {} try testBindOptionalFunctionParameter(throwingFunc) testBindOptionalFunctionParameter(nonThrowingFunc) testBindOptionalFunctionParameter(nil) try testImplicitlyUnwrappedFunctionParameter(throwingFunc) testImplicitlyUnwrappedFunctionParameter(nonThrowingFunc) testImplicitlyUnwrappedFunctionParameter(nil) /** Miscellaneous bugs **/ // rdar://problem/21967164 - Non-throwing closures are incorrectly marked as throwing in rethrow contexts func rt1(predicate: () throws -> ()) rethrows { } rt1 { } func rt2(_ predicate: () throws -> ()) rethrows { } rt2 { } enum SomeError : Error { case Badness } func testUnrelatedThrowsInRethrows(_ fn: () throws -> Void) rethrows { try fn() // okay try testUnrelatedThrowsInRethrows(fn) // okay raise() // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled; a function declared 'rethrows' may only throw if its parameter does}} try raise() // expected-error {{call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does}} throw SomeError.Badness // expected-error {{a function declared 'rethrows' may only throw if its parameter does}} } func testThrowsInCatchInRethrows(_ fn: () throws -> Void) rethrows { do { try fn() } catch { // this catch can only be entered if our `fn` parameter throws throw error // okay } do { try fn() } catch let error as SomeError { throw error // okay } do { try fn() try raise() } catch { // this catch can be entered regardless of whether our `fn` parameter throws throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}} } do { throw SomeError.Badness } catch { // this catch can be entered regardless of whether our `fn` parameter throws throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}} } do { try fn() try raise() // expected-error {{call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does}} } catch is SomeError {} do { try raise() } catch { try fn() // okay } do { // don't throw anything; equivalent to throwing in an #if } catch { // expected-warning {{'catch' block is unreachable because no errors are thrown in 'do' block}} throw error } } // Soundness-check that throwing in catch blocks behaves as expected outside of // rethrows functions func testThrowsInCatch(_ fn: () throws -> Void) { do { try fn() } catch { throw error // expected-error {{error is not handled because the enclosing function is not declared 'throws'}} } } func testThrowsInCatchInThrows() throws { do { try raise() } catch { throw error // okay } } // Bogus "no calls to throwing functions" warning in derived throwing init class B24221830 {} class r24221830 : B24221830 { var B: Int init(A: String) throws { self.B = 0 } } // rdar://problem/30618853 func gallant(_: () throws -> ()) rethrows {} func goofus(_ f: () -> ()) { gallant(f) main.gallant(f) } func goofus(_ f: () throws -> ()) rethrows { try gallant(f) try main.gallant(f) } struct Foo { func foo() {} } func throwWhileGettingFoo() throws -> Foo.Type { return Foo.self } (throwWhileGettingFoo()).foo(Foo())() // expected-error {{can throw}} // expected-note@-1 {{did you mean to use 'try'?}} {{2-2=try }} // expected-note@-2 {{did you mean to handle error as optional value?}} {{2-2=try? }} // expected-note@-3 {{did you mean to disable error propagation?}} {{2-2=try! }} (try throwWhileGettingFoo()).foo(Foo())() // [Source compatibility] Call to sort(by):) can throw, but is not marked with 'try' func doRethrow(fn: (Int, Int) throws -> Int) rethrows { } struct DoRethrowGeneric { func method(fn: (T, T) throws -> T) rethrows { } } func testDoRethrow() { doRethrow(fn:) { (a, b) in return a } DoRethrowGeneric().method(fn:) { (a, b) in return a } } // https://github.com/apple/swift/issues/49668 func rethrowsWithCaptureList( array: [T], operation: (Int) throws -> R ) rethrows -> R { return try array.withUnsafeBytes { [array] _ in return try operation(array.count) } } // rdar://problem/40472018: Crash on rethrows function with variadic parameter and throwing function parameter. public func variadic_rethrows(_ values: Int..., body: (Int) throws -> ()) rethrows { } public func rdar40472018() { variadic_rethrows(1, 2) { _ in } } // https://github.com/apple/swift/issues/48849 // Verify that we do not emit an invalid // "... can throw but the expression is not marked with 'try'" // error on the use of operators. infix operator <|: infixr0 infix operator |>: infixl1 precedencegroup infixr0 { associativity: right } precedencegroup infixl1 { associativity: left higherThan: infixr0 } func <| (f: (A) throws -> B, a: A) rethrows -> B { return try f(a) } func |> (a: A, f: (A) -> B) -> B { return try f(a) // expected-warning {{no calls to throwing functions occur within 'try' expression}} } struct Box { let unbox: A } func suchThat(_ x: Box) -> (@escaping (A) -> A) -> Box { return { f in Box(unbox: f(x.unbox)) } } Box(unbox: 1) |> suchThat <| { $0 + 1 } // expected-warning {{result of operator '<|' is unused}} // Constructor delegation -vs- rethrows class RethrowingConstructor { init(_ block: () throws -> ()) rethrows { try block() } convenience init(bar: Int) { self.init { print("Foo!") } } convenience init(baz: Int) throws { try self.init { try throwingFunc() } } } // default values -vs- throwing function inside optional func rdar_47550715() { typealias A = (T) -> Void typealias F = () throws -> Void func foo(_: A? = nil) {} // Ok func bar(_: A? = .none) {} // Ok } // https://github.com/apple/swift/issues/56630 // Test cases for diagnostic note 'because_rethrows_default_argument_throws' func nonThrowableDefaultRethrows(_ f: () throws -> () = {}) rethrows { try f() } // FIXME: This should compile and not emit a diagnostic because ideally the // compiler could statically know the default argument value could never throw. // (https://github.com/apple/swift/issues/44143) nonThrowableDefaultRethrows() // expected-error {{call can throw but is not marked with 'try'}} // expected-note@-1 {{call is to 'rethrows' function, but a defaulted argument function can throw}} func throwableDefaultRethrows(_ f: () throws -> () = { throw SomeError.Badness }) rethrows { try f() } // This should always emit a diagnostic because we can statically know that default argument can throw. throwableDefaultRethrows() // expected-error {{call can throw but is not marked with 'try'}} // expected-note@-1 {{call is to 'rethrows' function, but a defaulted argument function can throw}} // rdar://76169080 - rethrows -vs- Optional default arguments func optionalRethrowsDefaultArg1(_: (() throws -> ())? = nil) rethrows {} func callsOptionalRethrowsDefaultArg1() throws { optionalRethrowsDefaultArg1() optionalRethrowsDefaultArg1(nil) try optionalRethrowsDefaultArg1 { throw SomeError.Badness } } func optionalRethrowsDefaultArg2(_: (() throws -> ())? = { throw SomeError.Badness }) rethrows {} func callsOptionalRethrowsDefaultArg2() throws { optionalRethrowsDefaultArg2() // expected-error {{call can throw but is not marked with 'try'}} // expected-note@-1 {{call is to 'rethrows' function, but a defaulted argument function can throw}} optionalRethrowsDefaultArg2(nil) try optionalRethrowsDefaultArg2 { throw SomeError.Badness } } protocol P1 { var id: Int { get } func test(_: some Sequence) -> [any P1] } func open(p: any P1, s: any Sequence) throws { _ = p.test(s).map(\.id) } // Rethrows checking and parameter packs, oh my. func rethrowsWithParameterPacks(_ arguments: repeat each Arg, body: () throws -> Void) rethrows { } enum MyError: Error { case fail } func testRethrowsWithParameterPacks() throws { try rethrowsWithParameterPacks { throw MyError.fail } rethrowsWithParameterPacks { } try rethrowsWithParameterPacks(1) { throw MyError.fail } rethrowsWithParameterPacks(1) { } try rethrowsWithParameterPacks(1, "hello") { throw MyError.fail } rethrowsWithParameterPacks(1, "hello") { } rethrowsWithParameterPacks { throw MyError.fail } // expected-error@-1{{call can throw but is not marked with 'try'}} // expected-note@-2{{call is to 'rethrows' function, but argument function can throw}} } // Rethrows checking with the original parameter type providing the cues. func takesArbitraryAndRethrows(_ value: T, body: () throws -> Void) rethrows { } func testArbitraryAndRethrows() { takesArbitraryAndRethrows(throwingFunc) { } }