Merge pull request #10706 from itaiferber/swift-4.0-branch

[4.0] Optionality updates to Codable API
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index 3b67caf..fdb2b39 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -1104,7 +1104,7 @@
           }
         }
 
-        TC.diagnose(startLoc, diag::non_exhaustive_switch);
+        TC.diagnose(startLoc, mainDiagType);
         TC.diagnose(startLoc, diag::missing_several_cases, false)
           .fixItInsert(endLoc, buffer.str());
       } else {
diff --git a/stdlib/public/SDK/Foundation/Codable.swift b/stdlib/public/SDK/Foundation/Codable.swift
index 4410933..200cbb1 100644
--- a/stdlib/public/SDK/Foundation/Codable.swift
+++ b/stdlib/public/SDK/Foundation/Codable.swift
@@ -14,59 +14,9 @@
 // Errors
 //===----------------------------------------------------------------------===//
 
-// Adding the following extensions to EncodingError and DecodingError allows them to bridge to NSErrors implicitly.
-
-fileprivate let NSCodingPathErrorKey = "NSCodingPath"
-fileprivate let NSDebugDescriptionErrorKey = "NSDebugDescription"
-
-extension EncodingError : CustomNSError {
-    public static var errorDomain: String = NSCocoaErrorDomain
-
-    public var errorCode: Int {
-        switch self {
-        case .invalidValue(_, _): return CocoaError.coderInvalidValue.rawValue
-        }
-    }
-
-    public var errorUserInfo: [String : Any] {
-        let context: Context
-        switch self {
-        case .invalidValue(_, let c): context = c
-        }
-
-        return [NSCodingPathErrorKey: context.codingPath,
-                NSDebugDescriptionErrorKey: context.debugDescription]
-    }
-}
-
-extension DecodingError : CustomNSError {
-    public static var errorDomain: String = NSCocoaErrorDomain
-
-    public var errorCode: Int {
-        switch self {
-        case .valueNotFound(_, _): fallthrough
-        case .keyNotFound(_, _):
-            return CocoaError._coderValueNotFound.rawValue
-
-        case .typeMismatch(_, _): fallthrough
-        case .dataCorrupted(_):
-            return CocoaError._coderReadCorrupt.rawValue
-        }
-    }
-
-    public var errorUserInfo: [String : Any]? {
-        let context: Context
-        switch self {
-        case .typeMismatch(_, let c): context = c
-        case .valueNotFound(_, let c): context = c
-        case .keyNotFound(_, let c): context = c
-        case .dataCorrupted(let c): context = c
-        }
-
-        return [NSCodingPathErrorKey: context.codingPath,
-                NSDebugDescriptionErrorKey: context.debugDescription]
-    }
-}
+// Both of these error types bridge to NSError, and through the entry points they use, no further work is needed to make them localized.
+extension EncodingError : LocalizedError {}
+extension DecodingError : LocalizedError {}
 
 //===----------------------------------------------------------------------===//
 // Error Utilities
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index 14e38d9..65a5e54 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -62,8 +62,11 @@
 
     /// The strategy to use for encoding `Data` values.
     public enum DataEncodingStrategy {
+        /// Defer to `Data` for choosing an encoding.
+        case deferredToData
+
         /// Encoded the `Data` as a Base64-encoded string. This is the default strategy.
-        case base64Encode
+        case base64
 
         /// Encode the `Data` as a custom value encoded by the given closure.
         ///
@@ -86,8 +89,8 @@
     /// The strategy to use in encoding dates. Defaults to `.deferredToDate`.
     open var dateEncodingStrategy: DateEncodingStrategy = .deferredToDate
 
-    /// The strategy to use in encoding binary data. Defaults to `.base64Encode`.
-    open var dataEncodingStrategy: DataEncodingStrategy = .base64Encode
+    /// The strategy to use in encoding binary data. Defaults to `.base64`.
+    open var dataEncodingStrategy: DataEncodingStrategy = .base64
 
     /// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
     open var nonConformingFloatEncodingStrategy: NonConformingFloatEncodingStrategy = .throw
@@ -142,7 +145,11 @@
         }
 
         let writingOptions = JSONSerialization.WritingOptions(rawValue: self.outputFormatting.rawValue)
-        return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
+        do {
+           return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
+        } catch {
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Unable to encode the given top-level value to JSON.", underlyingError: error))
+        }
     }
 }
 
@@ -663,7 +670,12 @@
 
     fileprivate func box(_ data: Data) throws -> NSObject {
         switch self.options.dataEncodingStrategy {
-        case .base64Encode:
+        case .deferredToData:
+            // Must be called with a surrounding with(pushedKey:) call.
+            try data.encode(to: self)
+            return self.storage.popContainer()
+
+        case .base64:
             return NSString(string: data.base64EncodedString())
 
         case .custom(let closure):
@@ -815,8 +827,11 @@
 
     /// The strategy to use for decoding `Data` values.
     public enum DataDecodingStrategy {
+        /// Defer to `Data` for decoding.
+        case deferredToData
+
         /// Decode the `Data` from a Base64-encoded string. This is the default strategy.
-        case base64Decode
+        case base64
 
         /// Decode the `Data` as a custom value decoded by the given closure.
         case custom((_ decoder: Decoder) throws -> Data)
@@ -834,8 +849,8 @@
     /// The strategy to use in decoding dates. Defaults to `.deferredToDate`.
     open var dateDecodingStrategy: DateDecodingStrategy = .deferredToDate
 
-    /// The strategy to use in decoding binary data. Defaults to `.base64Decode`.
-    open var dataDecodingStrategy: DataDecodingStrategy = .base64Decode
+    /// The strategy to use in decoding binary data. Defaults to `.base64`.
+    open var dataDecodingStrategy: DataDecodingStrategy = .base64
 
     /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
     open var nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy = .throw
@@ -874,7 +889,13 @@
     /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not valid JSON.
     /// - throws: An error if any value throws an error during decoding.
     open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
-        let topLevel = try JSONSerialization.jsonObject(with: data)
+        let topLevel: Any
+        do {
+           topLevel = try JSONSerialization.jsonObject(with: data)
+        } catch {
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
+        }
+
         let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
         return try T(from: decoder)
     }
@@ -2037,7 +2058,13 @@
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dataDecodingStrategy {
-        case .base64Decode:
+        case .deferredToData:
+            self.storage.push(container: value)
+            let data = try Data(from: self)
+            self.storage.popContainer()
+            return data
+
+        case .base64:
             guard let string = value as? String else {
                 throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
             }
diff --git a/stdlib/public/SDK/Foundation/NSError.swift b/stdlib/public/SDK/Foundation/NSError.swift
index 768fb26..3b3c585 100644
--- a/stdlib/public/SDK/Foundation/NSError.swift
+++ b/stdlib/public/SDK/Foundation/NSError.swift
@@ -850,19 +850,11 @@
 
   @available(OSX, introduced: 10.11) @available(iOS, introduced: 9.0)
   public static var coderReadCorrupt: CocoaError.Code {
-    return _coderReadCorrupt
-  }
-
-  internal static var _coderReadCorrupt: CocoaError.Code {
     return CocoaError.Code(rawValue: 4864)
   }
 
   @available(OSX, introduced: 10.11) @available(iOS, introduced: 9.0)
   public static var coderValueNotFound: CocoaError.Code {
-    return _coderValueNotFound
-  }
-
-  internal static var _coderValueNotFound: CocoaError.Code {
     return CocoaError.Code(rawValue: 4865)
   }
 
@@ -1301,19 +1293,11 @@
 
   @available(OSX, introduced: 10.11) @available(iOS, introduced: 9.0)
   public static var coderReadCorrupt: CocoaError.Code {
-    return _coderReadCorrupt
-  }
-
-  public static var _coderReadCorrupt: CocoaError.Code {
     return CocoaError.Code(rawValue: 4864)
   }
 
   @available(OSX, introduced: 10.11) @available(iOS, introduced: 9.0)
   public static var coderValueNotFound: CocoaError.Code {
-    return _coderValueNotFound
-  }
-
-  internal static var _coderValueNotFound: CocoaError.Code {
     return CocoaError.Code(rawValue: 4865)
   }
 
diff --git a/stdlib/public/SDK/Foundation/PlistEncoder.swift b/stdlib/public/SDK/Foundation/PlistEncoder.swift
index 35cfdfd..b7e4d2f 100644
--- a/stdlib/public/SDK/Foundation/PlistEncoder.swift
+++ b/stdlib/public/SDK/Foundation/PlistEncoder.swift
@@ -74,7 +74,11 @@
                                                                    debugDescription: "Top-level \(Value.self) encoded as date property list fragment."))
         }
 
-        return try PropertyListSerialization.data(fromPropertyList: topLevel, format: self.outputFormat, options: 0)
+        do {
+            return try PropertyListSerialization.data(fromPropertyList: topLevel, format: self.outputFormat, options: 0)
+        } catch {
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Unable to encode the given top-level value as a property list", underlyingError: error))
+        }
     }
 }
 
@@ -642,7 +646,12 @@
     /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not a valid property list.
     /// - throws: An error if any value throws an error during decoding.
     open func decode<T : Decodable>(_ type: T.Type, from data: Data, format: inout PropertyListSerialization.PropertyListFormat) throws -> T {
-        let topLevel = try PropertyListSerialization.propertyList(from: data, options: [], format: &format)
+        let topLevel: Any
+        do {
+            topLevel = try PropertyListSerialization.propertyList(from: data, options: [], format: &format)
+        } catch {
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not a valid property list.", underlyingError: error))
+        }
         let decoder = _PlistDecoder(referencing: topLevel, options: self.options)
         return try T(from: decoder)
     }
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index 6d437d7..1cd4209 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -2096,6 +2096,10 @@
 /// A container that can support the storage and direct encoding of a single
 /// non-keyed value.
 public protocol SingleValueEncodingContainer {
+    /// The path of coding keys taken to get to this point in encoding.
+    /// A `nil` value indicates an unkeyed container.
+    var codingPath: [CodingKey?] { get }
+
     /// Encodes a null value.
     ///
     /// - throws: `EncodingError.invalidValue` if a null value is invalid in the current context for this format.
@@ -2210,6 +2214,10 @@
 
 /// A `SingleValueDecodingContainer` is a container which can support the storage and direct decoding of a single non-keyed value.
 public protocol SingleValueDecodingContainer {
+    /// The path of coding keys taken to get to this point in encoding.
+    /// A `nil` value indicates an unkeyed container.
+    var codingPath: [CodingKey?] { get }
+
     /// Decodes a null value.
     ///
     /// - returns: Whether the encountered value was null.
@@ -2382,13 +2390,18 @@
         /// A description of what went wrong, for debugging purposes.
         public let debugDescription: String
 
+        /// The underlying error which caused this error, if any.
+        public let underlyingError: Error?
+
         /// Initializes `self` with the given path of `CodingKey`s and a description of what went wrong.
         ///
         /// - parameter codingPath: The path of `CodingKey`s taken to get to the point of the failing encode call.
         /// - parameter debugDescription: A description of what went wrong, for debugging purposes.
-        public init(codingPath: [CodingKey?], debugDescription: String) {
+        /// - parameter underlyingError: The underlying error which caused this error, if any.
+        public init(codingPath: [CodingKey?], debugDescription: String, underlyingError: Error? = nil) {
             self.codingPath = codingPath
             self.debugDescription = debugDescription
+            self.underlyingError = underlyingError
         }
     }
 
@@ -2396,6 +2409,44 @@
     ///
     /// Contains the attempted value, along with context for debugging.
     case invalidValue(Any, Context)
+
+    // MARK: - NSError Bridging
+
+    // CustomNSError bridging applies only when the CustomNSError conformance is applied in the same module as the declared error type.
+    // Since we cannot access CustomNSError (which is defined in Foundation) from here, we can use the "hidden" entry points.
+
+    public var _domain: String {
+        return "NSCocoaErrorDomain"
+    }
+
+    public var _code: Int {
+        switch self {
+        case .invalidValue(_, _): return 4866
+        }
+    }
+
+    public var _userInfo: AnyObject? {
+        // The error dictionary must be returned as an AnyObject. We can do this only on platforms with bridging, unfortunately.
+        #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+            let context: Context
+            switch self {
+            case .invalidValue(_, let c): context = c
+            }
+
+            var userInfo: [String : Any] = [
+                "NSCodingPath": context.codingPath,
+                "NSDebugDescription": context.debugDescription
+            ]
+
+            if let underlyingError = context.underlyingError {
+                userInfo["NSUnderlyingError"] = underlyingError
+            }
+
+            return userInfo as AnyObject
+        #else
+            return nil
+        #endif
+    }
 }
 
 /// An error that occurs during the decoding of a value.
@@ -2408,13 +2459,18 @@
         /// A description of what went wrong, for debugging purposes.
         public let debugDescription: String
 
+        /// The underlying error which caused this error, if any.
+        public let underlyingError: Error?
+
         /// Initializes `self` with the given path of `CodingKey`s and a description of what went wrong.
         ///
         /// - parameter codingPath: The path of `CodingKey`s taken to get to the point of the failing decode call.
         /// - parameter debugDescription: A description of what went wrong, for debugging purposes.
-        public init(codingPath: [CodingKey?], debugDescription: String) {
+        /// - parameter underlyingError: The underlying error which caused this error, if any.
+        public init(codingPath: [CodingKey?], debugDescription: String, underlyingError: Error? = nil) {
             self.codingPath = codingPath
             self.debugDescription = debugDescription
+            self.underlyingError = underlyingError
         }
     }
 
@@ -2437,6 +2493,91 @@
     ///
     /// Contains context for debugging.
     case dataCorrupted(Context)
+
+    // MARK: - NSError Bridging
+
+    // CustomNSError bridging applies only when the CustomNSError conformance is applied in the same module as the declared error type.
+    // Since we cannot access CustomNSError (which is defined in Foundation) from here, we can use the "hidden" entry points.
+
+    public var _domain: String {
+        return "NSCocoaErrorDomain"
+    }
+
+    public var _code: Int {
+        switch self {
+        case .keyNotFound(_, _):   fallthrough
+        case .valueNotFound(_, _): return 4865
+        case .typeMismatch(_, _):  fallthrough
+        case .dataCorrupted(_):    return 4864
+        }
+    }
+
+    public var _userInfo: AnyObject? {
+        // The error dictionary must be returned as an AnyObject. We can do this only on platforms with bridging, unfortunately.
+        #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+            let context: Context
+            switch self {
+            case .keyNotFound(_,   let c): context = c
+            case .valueNotFound(_, let c): context = c
+            case .typeMismatch(_,  let c): context = c
+            case .dataCorrupted(   let c): context = c
+            }
+
+            var userInfo: [String : Any] = [
+                "NSCodingPath": context.codingPath,
+                "NSDebugDescription": context.debugDescription
+            ]
+
+            if let underlyingError = context.underlyingError {
+                userInfo["NSUnderlyingError"] = underlyingError
+            }
+
+            return userInfo as AnyObject
+        #else
+            return nil
+        #endif
+    }
+}
+
+// The following extensions allow for easier error construction.
+
+public extension DecodingError {
+    /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
+    ///
+    /// Constructs a coding path by appending the given key to the given container's coding path.
+    ///
+    /// - param key: The key which caused the failure.
+    /// - param container: The container in which the corrupted data was accessed.
+    /// - param debugDescription: A description of the error to aid in debugging.
+    static func dataCorruptedError<C : KeyedDecodingContainerProtocol>(forKey key: C.Key, in container: C, debugDescription: String) -> DecodingError {
+        let context = DecodingError.Context(codingPath: container.codingPath + [key],
+                                            debugDescription: debugDescription)
+        return .dataCorrupted(context)
+    }
+
+    /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
+    ///
+    /// Constructs a coding path by appending a nil key to the given container's coding path.
+    ///
+    /// - param container: The container in which the corrupted data was accessed.
+    /// - param debugDescription: A description of the error to aid in debugging.
+    static func dataCorruptedError(in container: UnkeyedDecodingContainer, debugDescription: String) -> DecodingError {
+        let context = DecodingError.Context(codingPath: container.codingPath + [nil],
+                                            debugDescription: debugDescription)
+        return .dataCorrupted(context)
+    }
+
+    /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
+    ///
+    /// Uses the given container's coding path as the constructed path.
+    ///
+    /// - param container: The container in which the corrupted data was accessed.
+    /// - param debugDescription: A description of the error to aid in debugging.
+    static func dataCorruptedError(in container: SingleValueDecodingContainer, debugDescription: String) -> DecodingError {
+        let context = DecodingError.Context(codingPath: container.codingPath,
+                                            debugDescription: debugDescription)
+        return .dataCorrupted(context)
+    }
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/test/stdlib/TestJSONEncoder.swift b/test/stdlib/TestJSONEncoder.swift
index f6218a6..9362421 100644
--- a/test/stdlib/TestJSONEncoder.swift
+++ b/test/stdlib/TestJSONEncoder.swift
@@ -134,7 +134,7 @@
 
   // MARK: - Date Strategy Tests
   func testEncodingDate() {
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     _testRoundTrip(of: TopLevelWrapper(Date()))
   }
 
@@ -143,7 +143,7 @@
     let seconds = 1000.0
     let expectedJSON = "{\"value\":1000}".data(using: .utf8)!
 
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     _testRoundTrip(of: TopLevelWrapper(Date(timeIntervalSince1970: seconds)),
                    expectedJSON: expectedJSON,
                    dateEncodingStrategy: .secondsSince1970,
@@ -155,7 +155,7 @@
     let seconds = 1000.0
     let expectedJSON = "{\"value\":1000000}".data(using: .utf8)!
 
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     _testRoundTrip(of: TopLevelWrapper(Date(timeIntervalSince1970: seconds)),
                    expectedJSON: expectedJSON,
                    dateEncodingStrategy: .millisecondsSince1970,
@@ -170,7 +170,7 @@
       let timestamp = Date(timeIntervalSince1970: 1000)
       let expectedJSON = "{\"value\":\"\(formatter.string(from: timestamp))\"}".data(using: .utf8)!
 
-      // We can't encode a top-level Date, so it'll be wrapped in an array.
+      // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
       _testRoundTrip(of: TopLevelWrapper(timestamp),
                      expectedJSON: expectedJSON,
                      dateEncodingStrategy: .iso8601,
@@ -186,7 +186,7 @@
     let timestamp = Date(timeIntervalSince1970: 1000)
     let expectedJSON = "{\"value\":\"\(formatter.string(from: timestamp))\"}".data(using: .utf8)!
 
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     _testRoundTrip(of: TopLevelWrapper(timestamp),
                    expectedJSON: expectedJSON,
                    dateEncodingStrategy: .formatted(formatter),
@@ -203,7 +203,7 @@
     }
     let decode = { (_: Decoder) throws -> Date in return timestamp }
 
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     let expectedJSON = "{\"value\":42}".data(using: .utf8)!
     _testRoundTrip(of: TopLevelWrapper(timestamp),
                    expectedJSON: expectedJSON,
@@ -218,7 +218,7 @@
     let encode = { (_: Date, _: Encoder) throws -> Void in }
     let decode = { (_: Decoder) throws -> Date in return timestamp }
 
-    // We can't encode a top-level Date, so it'll be wrapped in an array.
+    // We can't encode a top-level Date, so it'll be wrapped in a dictionary.
     let expectedJSON = "{\"value\":{}}".data(using: .utf8)!
     _testRoundTrip(of: TopLevelWrapper(timestamp),
                    expectedJSON: expectedJSON,
@@ -227,10 +227,21 @@
   }
 
   // MARK: - Data Strategy Tests
+  func testEncodingData() {
+    let data = Data(bytes: [0xDE, 0xAD, 0xBE, 0xEF])
+
+    // We can't encode a top-level Data, so it'll be wrapped in a dictionary.
+    let expectedJSON = "{\"value\":[222,173,190,239]}".data(using: .utf8)!
+    _testRoundTrip(of: TopLevelWrapper(data),
+                   expectedJSON: expectedJSON,
+                   dataEncodingStrategy: .deferredToData,
+                   dataDecodingStrategy: .deferredToData)
+  }
+
   func testEncodingBase64Data() {
     let data = Data(bytes: [0xDE, 0xAD, 0xBE, 0xEF])
 
-    // We can't encode a top-level Data, so it'll be wrapped in an array.
+    // We can't encode a top-level Data, so it'll be wrapped in a dictionary.
     let expectedJSON = "{\"value\":\"3q2+7w==\"}".data(using: .utf8)!
     _testRoundTrip(of: TopLevelWrapper(data), expectedJSON: expectedJSON)
   }
@@ -243,7 +254,7 @@
     }
     let decode = { (_: Decoder) throws -> Data in return Data() }
 
-    // We can't encode a top-level Data, so it'll be wrapped in an array.
+    // We can't encode a top-level Data, so it'll be wrapped in a dictionary.
     let expectedJSON = "{\"value\":42}".data(using: .utf8)!
     _testRoundTrip(of: TopLevelWrapper(Data()),
                    expectedJSON: expectedJSON,
@@ -256,7 +267,7 @@
     let encode = { (_: Data, _: Encoder) throws -> Void in }
     let decode = { (_: Decoder) throws -> Data in return Data() }
 
-    // We can't encode a top-level Data, so it'll be wrapped in an array.
+    // We can't encode a top-level Data, so it'll be wrapped in a dictionary.
     let expectedJSON = "{\"value\":{}}".data(using: .utf8)!
     _testRoundTrip(of: TopLevelWrapper(Data()),
                    expectedJSON: expectedJSON,
@@ -363,8 +374,8 @@
                                  outputFormatting: JSONEncoder.OutputFormatting = [],
                                  dateEncodingStrategy: JSONEncoder.DateEncodingStrategy = .deferredToDate,
                                  dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,
-                                 dataEncodingStrategy: JSONEncoder.DataEncodingStrategy = .base64Encode,
-                                 dataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64Decode,
+                                 dataEncodingStrategy: JSONEncoder.DataEncodingStrategy = .base64,
+                                 dataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64,
                                  nonConformingFloatEncodingStrategy: JSONEncoder.NonConformingFloatEncodingStrategy = .throw,
                                  nonConformingFloatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw) where T : Codable, T : Equatable {
     var payload: Data! = nil
@@ -919,6 +930,7 @@
 JSONEncoderTests.test("testEncodingDateFormatted") { TestJSONEncoder().testEncodingDateFormatted() }
 JSONEncoderTests.test("testEncodingDateCustom") { TestJSONEncoder().testEncodingDateCustom() }
 JSONEncoderTests.test("testEncodingDateCustomEmpty") { TestJSONEncoder().testEncodingDateCustomEmpty() }
+JSONEncoderTests.test("testEncodingData") { TestJSONEncoder().testEncodingData() }
 JSONEncoderTests.test("testEncodingBase64Data") { TestJSONEncoder().testEncodingBase64Data() }
 JSONEncoderTests.test("testEncodingCustomData") { TestJSONEncoder().testEncodingCustomData() }
 JSONEncoderTests.test("testEncodingCustomDataEmpty") { TestJSONEncoder().testEncodingCustomDataEmpty() }
diff --git a/test/stmt/nonexhaustive_switch_stmt_editor.swift b/test/stmt/nonexhaustive_switch_stmt_editor.swift
new file mode 100644
index 0000000..ee5d862
--- /dev/null
+++ b/test/stmt/nonexhaustive_switch_stmt_editor.swift
@@ -0,0 +1,29 @@
+// RUN: %target-typecheck-verify-swift -diagnostics-editor-mode
+
+typealias TimeInterval = Double
+
+let NSEC_PER_USEC : UInt64 = 1000
+let NSEC_PER_SEC : UInt64 = 1000000000
+
+public enum TemporalProxy {
+  case seconds(Int)
+  case milliseconds(Int)
+  case microseconds(Int)
+  case nanoseconds(Int)
+  @_downgrade_exhaustivity_check
+  case never
+}
+
+func unproxify(t : TemporalProxy) -> TimeInterval {
+  switch t { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{do you want to add missing cases?}}
+  case let .seconds(s):
+    return TimeInterval(s)
+  case let .milliseconds(ms):
+    return TimeInterval(TimeInterval(ms) / 1000.0)
+  case let .microseconds(us):
+    return TimeInterval( UInt64(us) * NSEC_PER_USEC ) / TimeInterval(NSEC_PER_SEC)
+  case let .nanoseconds(ns):
+    return TimeInterval(ns) / TimeInterval(NSEC_PER_SEC)
+  }
+}