From 6f2fedde9ee20700eda6aebd1963a15087556ef2 Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Sun, 20 Mar 2016 13:33:32 -0700 Subject: [PATCH 1/2] [stdlib] SE-0061: Add Generic Result and Error Handling to autoreleasepool() Added `rethrows` and generic return type to ObjectiveC.autoreleasepool. Added tests of these new capabilities. Fixes SR-1394 and SR-842 --- stdlib/public/SDK/ObjectiveC/ObjectiveC.swift | 10 +++--- test/Interpreter/SDK/autorelease.swift | 36 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift index 8839665049d97..71d818b6b246b 100644 --- a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift +++ b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift @@ -181,7 +181,7 @@ public struct NSZone { typealias Zone = NSZone //===----------------------------------------------------------------------===// -// FIXME: @autoreleasepool substitute +// @autoreleasepool substitute //===----------------------------------------------------------------------===// @warn_unused_result @@ -191,10 +191,12 @@ func __pushAutoreleasePool() -> OpaquePointer @_silgen_name("_swift_objc_autoreleasePoolPop") func __popAutoreleasePool(_ pool: OpaquePointer) -public func autoreleasepool(_ code: @noescape () -> Void) { +public func autoreleasepool(_ body: @noescape () throws -> Result) rethrows -> Result { let pool = __pushAutoreleasePool() - code() - __popAutoreleasePool(pool) + defer { + __popAutoreleasePool(pool) + } + return try body() } //===----------------------------------------------------------------------===// diff --git a/test/Interpreter/SDK/autorelease.swift b/test/Interpreter/SDK/autorelease.swift index ef5436795c421..e3c8c0be39e5d 100644 --- a/test/Interpreter/SDK/autorelease.swift +++ b/test/Interpreter/SDK/autorelease.swift @@ -34,3 +34,39 @@ print("autorelease test end") // CHECK-NEXT: object died // CHECK-NEXT: after call to useTemp // CHECK-NEXT: autorelease test end + +// Using an @objc class to check that errors are retained across the pool +// boundaries. A classic crash is an error created inside a pool and then +// zombied before handling it outside the pool. +@objc class Error: NSObject, ErrorProtocol { + let message:String + init(message:String) { + self.message = message + } +} + +// Check that rethrow works. +func requireString(string:String?) throws -> String { + guard let string = string else { + throw Error(message:"no string") + } + print("returning \"\(string)\"") + return string +} +do { + try autoreleasepool { + try requireString(string: "ok") + try requireString(string: nil) + } +} catch let err as Error { + print("caught \"\(err.message)\"") +} +// CHECK-NEXT: returning "ok" +// CHECK-NEXT: caught "no string" + +// Check that a return value can be passed back. +let result = try autoreleasepool { + return "a string" +} +print("result = \"\(result)\"") +// CHECK-NEXT: result = "a string" From b5e3938e7b4735224ac119cea308f1cf7e92077f Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Wed, 4 May 2016 08:37:00 -0700 Subject: [PATCH 2/2] Updated for code style review. --- stdlib/public/SDK/ObjectiveC/ObjectiveC.swift | 4 +++- test/Interpreter/SDK/autorelease.swift | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift index 71d818b6b246b..d547adef51a51 100644 --- a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift +++ b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift @@ -191,7 +191,9 @@ func __pushAutoreleasePool() -> OpaquePointer @_silgen_name("_swift_objc_autoreleasePoolPop") func __popAutoreleasePool(_ pool: OpaquePointer) -public func autoreleasepool(_ body: @noescape () throws -> Result) rethrows -> Result { +public func autoreleasepool( + _ body: @noescape () throws -> Result +) rethrows -> Result { let pool = __pushAutoreleasePool() defer { __popAutoreleasePool(pool) diff --git a/test/Interpreter/SDK/autorelease.swift b/test/Interpreter/SDK/autorelease.swift index e3c8c0be39e5d..ee9a3b2583991 100644 --- a/test/Interpreter/SDK/autorelease.swift +++ b/test/Interpreter/SDK/autorelease.swift @@ -38,17 +38,17 @@ print("autorelease test end") // Using an @objc class to check that errors are retained across the pool // boundaries. A classic crash is an error created inside a pool and then // zombied before handling it outside the pool. -@objc class Error: NSObject, ErrorProtocol { - let message:String - init(message:String) { +@objc class Error : NSObject, ErrorProtocol { + let message: String + init(message: String) { self.message = message } } // Check that rethrow works. -func requireString(string:String?) throws -> String { +func requireString(string: String?) throws -> String { guard let string = string else { - throw Error(message:"no string") + throw Error(message: "no string") } print("returning \"\(string)\"") return string