Merge pull request #1185 from weissi/jw-test-http-server-auto-port

diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c
index 5f67510..6dd5564 100644
--- a/CoreFoundation/Base.subproj/CFPlatform.c
+++ b/CoreFoundation/Base.subproj/CFPlatform.c
@@ -180,6 +180,12 @@
     }
     return __CFProcessPath;
 }
+
+#else
+
+Boolean _CFIsMainThread(void) {
+    return pthread_main_np() == 1;
+}
 #endif
 
 CF_PRIVATE CFStringRef _CFProcessNameString(void) {
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index c580409..ea62f88 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -27,6 +27,7 @@
 #include <CoreFoundation/ForFoundationOnly.h>
 #include <fts.h>
 #include <pthread.h>
+#include <execinfo.h>
 
 _CF_EXPORT_SCOPE_BEGIN
 
@@ -294,6 +295,7 @@
 CF_EXPORT void CFLog1(CFLogLevel lev, CFStringRef message);
 
 CF_EXPORT Boolean _CFIsMainThread(void);
+CF_EXPORT pthread_t _CFMainPThread;
 
 CF_EXPORT CFHashCode __CFHashDouble(double d);
 
diff --git a/Docs/Status.md b/Docs/Status.md
index 13c9cfd..fa06c03 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -278,7 +278,7 @@
     | `Process`        | Mostly Complete | Substantial   | `interrupt()`, `terminate()`, `suspend()`, and `resume()` remain unimplemented                                            |
     | `Bundle`         | Mostly Complete | Incomplete    | `allBundles`, `init(for:)`, `unload()`, `classNamed()`, and `principalClass` remain unimplemented                         |
     | `ProcessInfo`    | Complete        | Substantial   |                                                                                                                           |
-    | `Thread`         | Incomplete      | Incomplete    | `isMainThread`, `mainThread`, `name`, `callStackReturnAddresses`, and `callStackSymbols` remain unimplemented             |
+    | `Thread`         | Complete        | Incomplete    |                                                                                                                           |
     | `Operation`      | Complete        | Incomplete    |                                                                                                                           |
     | `BlockOperation` | Complete        | Incomplete    |                                                                                                                           |
     | `OperationQueue` | Complete        | Incomplete    |                                                                                                                           |
diff --git a/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj
index ae314b4..5461afe 100644
--- a/Foundation.xcodeproj/project.pbxproj
+++ b/Foundation.xcodeproj/project.pbxproj
@@ -14,6 +14,7 @@
 		231503DB1D8AEE5D0061694D /* TestDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestDecimal.swift */; };
 		294E3C1D1CC5E19300E4F44C /* TestNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */; };
 		2EBE67A51C77BF0E006583D5 /* TestDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */; };
+		3E55A2331F52463B00082000 /* TestUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E55A2321F52463B00082000 /* TestUnit.swift */; };
 		3EA9D6701EF0532D00B362D6 /* TestJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */; };
 		3EDCE50C1EF04D8100C2EC04 /* Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5051EF04D8100C2EC04 /* Codable.swift */; };
 		3EDCE5101EF04D8100C2EC04 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */; };
@@ -490,6 +491,7 @@
 		231503DA1D8AEE5D0061694D /* TestDecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDecimal.swift; sourceTree = "<group>"; };
 		294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSAttributedString.swift; sourceTree = "<group>"; };
 		2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDateFormatter.swift; sourceTree = "<group>"; };
+		3E55A2321F52463B00082000 /* TestUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUnit.swift; sourceTree = "<group>"; };
 		3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestJSONEncoder.swift; sourceTree = "<group>"; };
 		3EDCE5051EF04D8100C2EC04 /* Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Codable.swift; sourceTree = "<group>"; };
 		3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONEncoder.swift; sourceTree = "<group>"; };
@@ -1494,6 +1496,7 @@
 				D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
 				5B6F17961C48631C00935030 /* TestUtils.swift */,
 				03B6F5831F15F339004F25AF /* TestURLProtocol.swift */,
+				3E55A2321F52463B00082000 /* TestUnit.swift */,
 			);
 			name = Tests;
 			sourceTree = "<group>";
@@ -2419,6 +2422,7 @@
 				F9E0BB371CA70B8000F7FF3C /* TestURLCredential.swift in Sources */,
 				5B13B3341C582D4C00651CE2 /* TestNSKeyedArchiver.swift in Sources */,
 				5B13B3441C582D4C00651CE2 /* TestNSSet.swift in Sources */,
+				3E55A2331F52463B00082000 /* TestUnit.swift in Sources */,
 				5B13B3321C582D4C00651CE2 /* TestIndexSet.swift in Sources */,
 				5B13B3511C582D4C00651CE2 /* TestByteCountFormatter.swift in Sources */,
 				BDFDF0A71DFF5B3E00C04CC5 /* TestPersonNameComponents.swift in Sources */,
diff --git a/Foundation/HTTPCookieStorage.swift b/Foundation/HTTPCookieStorage.swift
index 2e9e080..045b69d 100644
--- a/Foundation/HTTPCookieStorage.swift
+++ b/Foundation/HTTPCookieStorage.swift
@@ -49,7 +49,7 @@
         let bundlePath = Bundle.main.bundlePath
         var bundleName = bundlePath.components(separatedBy: "/").last!
         if let range = bundleName.range(of: ".", options: String.CompareOptions.backwards, range: nil, locale: nil) {
-            bundleName = bundleName.substring(to: range.lowerBound)
+            bundleName = String(bundleName[..<range.lowerBound])
         }
         let cookieFolderPath = _CFXDGCreateDataHomePath()._swiftObject + "/" + bundleName
         cookieFilePath = filePath(path: cookieFolderPath, fileName: "/.cookies." + cookieStorageName, bundleName: bundleName)
diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift
index d4a1201..a7b011f 100644
--- a/Foundation/JSONSerialization.swift
+++ b/Foundation/JSONSerialization.swift
@@ -577,9 +577,12 @@
             writer(" ")
         }
     }
-    
+
     //[SR-2151] https://bugs.swift.org/browse/SR-2151
     private mutating func _serializationString(for number: NSNumber) -> String {
+        if !CFNumberIsFloatType(number._cfObject) {
+            return number.stringValue
+        }
         return CFNumberFormatterCreateStringWithNumber(nil, _numberformatter, number._cfObject)._swiftObject
     }
 }
diff --git a/Foundation/Measurement.swift b/Foundation/Measurement.swift
index 99f6904..b119af1 100644
--- a/Foundation/Measurement.swift
+++ b/Foundation/Measurement.swift
@@ -275,3 +275,60 @@
         return Measurement(value: source!.doubleValue, unit: u)
     }
 }
+
+extension Measurement : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case value
+        case unit
+    }
+
+    private enum UnitCodingKeys : Int, CodingKey {
+        case symbol
+        case converter
+    }
+
+    private enum LinearConverterCodingKeys : Int, CodingKey {
+        case coefficient
+        case constant
+    }
+
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        let value = try container.decode(Double.self, forKey: .value)
+
+        let unitContainer = try container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
+        let symbol = try unitContainer.decode(String.self, forKey: .symbol)
+
+        let unit: UnitType
+        if UnitType.self is Dimension.Type {
+            let converterContainer = try unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
+            let coefficient = try converterContainer.decode(Double.self, forKey: .coefficient)
+            let constant = try converterContainer.decode(Double.self, forKey: .constant)
+            let unitMetaType = (UnitType.self as! Dimension.Type)
+            unit = (unitMetaType.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant)) as! UnitType)
+        } else {
+            unit = UnitType(symbol: symbol)
+        }
+
+        self.init(value: value, unit: unit)
+    }
+
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(self.value, forKey: .value)
+
+        var unitContainer = container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
+        try unitContainer.encode(self.unit.symbol, forKey: .symbol)
+
+        if UnitType.self is Dimension.Type {
+            guard type(of: (self.unit as! Dimension).converter) is UnitConverterLinear.Type else {
+                preconditionFailure("Cannot encode a Measurement whose UnitType has a non-linear unit converter.")
+            }
+
+            let converter = (self.unit as! Dimension).converter as! UnitConverterLinear
+            var converterContainer = unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
+            try converterContainer.encode(converter.coefficient, forKey: .coefficient)
+            try converterContainer.encode(converter.constant, forKey: .constant)
+        }
+    }
+}
diff --git a/Foundation/NSData.swift b/Foundation/NSData.swift
index 6dd8048..97b269d 100644
--- a/Foundation/NSData.swift
+++ b/Foundation/NSData.swift
@@ -146,6 +146,7 @@
     public convenience init(bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)? = nil) {
         self.init(bytes: bytes, length: length, copy: false, deallocator: deallocator)
     }
+
     public convenience init(contentsOfFile path: String, options readOptionsMask: ReadingOptions = []) throws {
         let readResult = try NSData.readBytesFromFileWithExtendedAttributes(path, options: readOptionsMask)
         self.init(bytes: readResult.bytes, length: readResult.length, copy: false, deallocator: readResult.deallocator)
@@ -380,7 +381,10 @@
         }
         
         let length = Int(info.st_size)
-        
+        if length == 0 && (info.st_mode & S_IFMT == S_IFREG) {
+            return try readZeroSizeFile(fd)
+        }
+
         if options.contains(.alwaysMapped) {
             let data = mmap(nil, length, PROT_READ, MAP_PRIVATE, fd, 0)
             
@@ -414,6 +418,37 @@
             free(buffer)
         }
     }
+
+    internal static func readZeroSizeFile(_ fd: Int32) throws -> NSDataReadResult {
+        let blockSize = 1024 * 1024 // 1MB
+        var data: UnsafeMutableRawPointer? = nil
+        var bytesRead = 0
+        var amt = 0
+
+        repeat {
+            data = realloc(data, bytesRead + blockSize)
+            amt = read(fd, data!.advanced(by: bytesRead), blockSize)
+
+            // Dont continue on EINTR or EAGAIN as the file position may not
+            // have changed, see read(2).
+            if amt < 0 {
+                free(data!)
+                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil)
+            }
+            bytesRead += amt
+        } while amt > 0
+
+        if bytesRead == 0 {
+            free(data!)
+            data = malloc(0)
+        } else {
+            data = realloc(data, bytesRead) // shrink down the allocated block.
+        }
+
+        return NSDataReadResult(bytes: data!, length: bytesRead) { buffer, length in
+            free(buffer)
+        }
+    }
     
     internal func makeTemporaryFile(inDirectory dirPath: String) throws -> (Int32, String) {
         let template = dirPath._nsObject.appendingPathComponent("tmp.XXXXXX")
diff --git a/Foundation/NSLock.swift b/Foundation/NSLock.swift
index e166b80..f4b41d0 100644
--- a/Foundation/NSLock.swift
+++ b/Foundation/NSLock.swift
@@ -230,12 +230,16 @@
         }
         var ts = timespec()
         ts.tv_sec = Int(floor(ti))
-        ts.tv_nsec = Int((ti - Double(ts.tv_sec)) * 1000000000.0)
+        ts.tv_nsec = Int((ti - Double(ts.tv_sec)) * 1_000_000_000.0)
         var tv = timeval()
         withUnsafeMutablePointer(to: &tv) { t in
             gettimeofday(t, nil)
             ts.tv_sec += t.pointee.tv_sec
-            ts.tv_nsec += Int((t.pointee.tv_usec * 1000000) / 1000000000)
+            ts.tv_nsec += Int(t.pointee.tv_usec) * 1000
+            if ts.tv_nsec >= 1_000_000_000 {
+                ts.tv_sec += ts.tv_nsec / 1_000_000_000
+                ts.tv_nsec = ts.tv_nsec % 1_000_000_000
+            }
         }
         let retVal: Int32 = withUnsafePointer(to: &ts) { t in
             return pthread_cond_timedwait(cond, mutex, t)
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index b72bdeb..1759771 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -256,7 +256,7 @@
             fatalError("unsupported CFNumberType: '\(numberType)'")
         }
     }
-    
+
     deinit {
         _CFDeinit(self)
     }
@@ -536,13 +536,25 @@
         }
     }
 
+    private static let _numberFormatterForNilLocale: CFNumberFormatter = {
+        let formatter: CFNumberFormatter
+        formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
+        CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
+        return formatter
+    }()
+
     open func description(withLocale locale: Locale?) -> String {
+        // CFNumberFormatterCreateStringWithNumber() does not like numbers of type
+        // SInt128Type, as it loses the type when looking it up and treats it as
+        // an SInt64Type, so special case them.
+        if _CFNumberGetType2(_cfObject) == kCFNumberSInt128Type {
+            return String(format: "%@", unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
+        }
+
         let aLocale = locale
         let formatter: CFNumberFormatter
         if (aLocale == nil) {
-            formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
-            CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
-
+            formatter = NSNumber._numberFormatterForNilLocale
         } else {
             formatter = CFNumberFormatterCreate(nil, aLocale?._cfObject, kCFNumberFormatterDecimalStyle)
         }
diff --git a/Foundation/NSStringAPI.swift b/Foundation/NSStringAPI.swift
index a5e1b00..03ebc30 100644
--- a/Foundation/NSStringAPI.swift
+++ b/Foundation/NSStringAPI.swift
@@ -2,11 +2,11 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 //===----------------------------------------------------------------------===//
 //
@@ -14,6 +14,20 @@
 //
 //===----------------------------------------------------------------------===//
 
+// Important Note
+// ==============
+//
+// This file is shared between two projects:
+//
+// 1. https://github.com/apple/swift/tree/master/stdlib/public/SDK/Foundation
+// 2. https://github.com/apple/swift-corelibs-foundation/tree/master/Foundation
+//
+// If you change this file, you must update it in both places.
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+@_exported import Foundation // Clang module
+#endif
+
 // Open Issues
 // ===========
 //
@@ -34,70 +48,38 @@
     length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
 }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+// We only need this for UnsafeMutablePointer, but there's not currently a way
+// to write that constraint.
+extension Optional {
+  /// Invokes `body` with `nil` if `self` is `nil`; otherwise, passes the
+  /// address of `object` to `body`.
+  ///
+  /// This is intended for use with Foundation APIs that return an Objective-C
+  /// type via out-parameter where it is important to be able to *ignore* that
+  /// parameter by passing `nil`. (For some APIs, this may allow the
+  /// implementation to avoid some work.)
+  ///
+  /// In most cases it would be simpler to just write this code inline, but if
+  /// `body` is complicated than that results in unnecessarily repeated code.
+  internal func _withNilOrAddress<NSType : AnyObject, ResultType>(
+    of object: inout NSType?,
+    _ body:
+      (AutoreleasingUnsafeMutablePointer<NSType?>?) -> ResultType
+  ) -> ResultType {
+    return self == nil ? body(nil) : body(&object)
+  }
+}
+#endif
+
 extension String {
-
-  //===--- Bridging Helpers -----------------------------------------------===//
-  //===--------------------------------------------------------------------===//
-
-  /// The corresponding `NSString` - a convenience for bridging code.
-  var _ns: NSString {
-    return self._bridgeToObjectiveC()
-  }
-
-  /// Return an `Index` corresponding to the given offset in our UTF-16
-  /// representation.
-  func _index(_ utf16Index: Int) -> Index {
-    return Index(encodedOffset: utf16Index)
-  }
-
-  /// Return a `Range<Index>` corresponding to the given `NSRange` of
-  /// our UTF-16 representation.
-  func _range(_ r: NSRange) -> Range<Index> {
-    return _index(r.location)..<_index(r.location + r.length)
-  }
-
-  /// Return a `Range<Index>?` corresponding to the given `NSRange` of
-  /// our UTF-16 representation.
-  func _optionalRange(_ r: NSRange) -> Range<Index>? {
-    if r.location == NSNotFound {
-      return nil
-    }
-    return _range(r)
-  }
-
-  /// Invoke `body` on an `Int` buffer.  If `index` was converted from
-  /// non-`nil`, convert the buffer to an `Index` and write it into the
-  /// memory referred to by `index`
-  func _withOptionalOutParameter<Result>(
-    _ index: UnsafeMutablePointer<Index>?,
-    _ body: (UnsafeMutablePointer<Int>?) -> Result
-  ) -> Result {
-    var utf16Index: Int = 0
-    let result = (index != nil ? body(&utf16Index) : body(nil))
-    index?.pointee = self._index(utf16Index)
-    return result
-  }
-
-  /// Invoke `body` on an `NSRange` buffer.  If `range` was converted
-  /// from non-`nil`, convert the buffer to a `Range<Index>` and write
-  /// it into the memory referred to by `range`
-  func _withOptionalOutParameter<Result>(
-    _ range: UnsafeMutablePointer<Range<Index>>?,
-    _ body: (UnsafeMutablePointer<NSRange>?) -> Result
-  ) -> Result {
-    var nsRange = NSRange(location: 0, length: 0)
-    let result = (range != nil ? body(&nsRange) : body(nil))
-    range?.pointee = self._range(nsRange)
-    return result
-  }
-
   //===--- Class Methods --------------------------------------------------===//
   //===--------------------------------------------------------------------===//
 
   // @property (class) const NSStringEncoding *availableStringEncodings;
 
-  /// Returns an Array of the encodings string objects support
-  /// in the application's environment.
+  /// An array of the encodings that strings support in the application's
+  /// environment.
   public static var availableStringEncodings: [Encoding] {
     var result = [Encoding]()
     var p = NSString.availableStringEncodings
@@ -110,15 +92,20 @@
 
   // @property (class) NSStringEncoding defaultCStringEncoding;
 
-  /// Returns the C-string encoding assumed for any method accepting
-  /// a C string as an argument.
+  /// The C-string encoding assumed for any method accepting a C string as an
+  /// argument.
   public static var defaultCStringEncoding: Encoding {
     return Encoding(rawValue: NSString.defaultCStringEncoding)
   }
 
   // + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
 
-  /// Returns a human-readable string giving the name of a given encoding.
+  /// Returns a human-readable string giving the name of the specified encoding.
+  ///
+  /// - Parameter encoding: A string encoding. For possible values, see
+  ///   `String.Encoding`.
+  /// - Returns: A human-readable string giving the name of `encoding` in the
+  ///   current locale.
   public static func localizedName(
     of encoding: Encoding
   ) -> String {
@@ -137,15 +124,6 @@
       arguments: arguments)
   }
 
-  // + (NSString *)pathWithComponents:(NSArray *)components
-
-  /// Returns a string built from the strings in a given array
-  /// by concatenating them with a path separator between each pair.
-  @available(*, unavailable, message: "Use fileURL(withPathComponents:) on URL instead.")
-  public static func path(withComponents components: [String]) -> String {
-    return (NSURL.fileURL(withPathComponents: components)?.path)!
-  }
-
   //===--------------------------------------------------------------------===//
   // NSString factory functions that have a corresponding constructor
   // are omitted.
@@ -188,453 +166,18 @@
 
   // + (instancetype)stringWithUTF8String:(const char *)bytes
 
-  /// Produces a string created by copying the data from a given
+  /// Creates a string by copying the data from a given
   /// C array of UTF8-encoded bytes.
   public init?(utf8String bytes: UnsafePointer<CChar>) {
     if let ns = NSString(utf8String: bytes) {
-      self = ns._swiftObject
+      self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
     }
   }
+}
 
-  //===--- Instance Methods/Properties-------------------------------------===//
-  //===--------------------------------------------------------------------===//
-
-  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
-  // @property BOOL boolValue;
-
-  // - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
-
-  /// Returns a Boolean value that indicates whether the
-  /// `String` can be converted to a given encoding without loss of
-  /// information.
-  public func canBeConverted(to encoding: Encoding) -> Bool {
-    return _ns.canBeConverted(to: encoding.rawValue)
-  }
-
-  // @property NSString* capitalizedString
-
-  /// Produce a string with the first character from each word changed
-  /// to the corresponding uppercase value.
-  public var capitalized: String {
-    return _ns.capitalized as String
-  }
-
-  // @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
-
-  /// A capitalized representation of the `String` that is produced
-  /// using the current locale.
-  public var localizedCapitalized: String {
-    return _ns.localizedCapitalized
-  }
-
-  // - (NSString *)capitalizedStringWithLocale:(Locale *)locale
-
-  /// Returns a capitalized representation of the `String`
-  /// using the specified locale.
-  public func capitalized(with locale: Locale?) -> String {
-    return _ns.capitalized(with: locale) as String
-  }
-
-  // - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
-
-  /// Returns the result of invoking `compare:options:` with
-  /// `NSCaseInsensitiveSearch` as the only option.
-  public func caseInsensitiveCompare(_ aString: String) -> ComparisonResult {
-    return _ns.caseInsensitiveCompare(aString)
-  }
-
-  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
-  // - (unichar)characterAtIndex:(NSUInteger)index
-  //
-  // We have a different meaning for "Character" in Swift, and we are
-  // trying not to expose error-prone UTF-16 integer indexes
-
-  // - (NSString *)
-  //     commonPrefixWithString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-
-  /// Returns a string containing characters the `String` and a
-  /// given string have in common, starting from the beginning of each
-  /// up to the first characters that aren't equivalent.
-  public func commonPrefix(
-    with aString: String, options: CompareOptions = []) -> String {
-    return _ns.commonPrefix(with: aString, options: options)
-  }
-
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //     range:(NSRange)range
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //     range:(NSRange)range locale:(id)locale
-
-  /// Compares the string using the specified options and
-  /// returns the lexical ordering for the range.
-  public func compare(
-    _ aString: String,
-    options mask: CompareOptions = [],
-    range: Range<Index>? = nil,
-    locale: Locale? = nil
-  ) -> ComparisonResult {
-    // According to Ali Ozer, there may be some real advantage to
-    // dispatching to the minimal selector for the supplied options.
-    // So let's do that; the switch should compile away anyhow.
-    return locale != nil ? _ns.compare(
-      aString,
-      options: mask,
-      range: _toNSRange(
-        range ?? self.startIndex..<self.endIndex
-      ),
-      locale: locale?._bridgeToObjectiveC()
-    )
-
-    : range != nil ? _ns.compare(
-      aString,
-      options: mask,
-      range: _toNSRange(range!)
-    )
-
-    : !mask.isEmpty ? _ns.compare(aString, options: mask)
-
-    : _ns.compare(aString)
-  }
-
-  // - (NSUInteger)
-  //     completePathIntoString:(NSString **)outputName
-  //     caseSensitive:(BOOL)flag
-  //     matchesIntoArray:(NSArray **)outputArray
-  //     filterTypes:(NSArray *)filterTypes
-
-  /// Interprets the `String` as a path in the file system and
-  /// attempts to perform filename completion, returning a numeric
-  /// value that indicates whether a match was possible, and by
-  /// reference the longest path that matches the `String`.
-  /// Returns the actual number of matching paths.
-  public func completePath(
-    into outputName: UnsafeMutablePointer<String>? = nil,
-    caseSensitive: Bool,
-    matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
-    filterTypes: [String]? = nil
-  ) -> Int {
-
-    var outputNamePlaceholder: String?
-    var outputArrayPlaceholder = [String]()
-    let res = self._ns.completePath(
-        into: &outputNamePlaceholder,
-        caseSensitive: caseSensitive,
-        matchesInto: &outputArrayPlaceholder,
-        filterTypes: filterTypes
-    )
-    if let n = outputNamePlaceholder {
-        outputName?.pointee = n
-    } else {
-        outputName?.pointee = ""
-    }
-    outputArray?.pointee = outputArrayPlaceholder
-    return res
-  }
-
-  // - (NSArray *)
-  //     componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
-
-  /// Returns an array containing substrings from the `String`
-  /// that have been divided by characters in a given set.
-  public func components(separatedBy separator: CharacterSet) -> [String] {
-    return _ns.components(separatedBy: separator)
-  }
-
-
-  // - (NSArray *)componentsSeparatedByString:(NSString *)separator
-
-  /// Returns an array containing substrings from the `String`
-  /// that have been divided by a given separator.
-  public func components(separatedBy separator: String) -> [String] {
-    return _ns.components(separatedBy: separator)
-  }
-
-  // - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
-
-  /// Returns a representation of the `String` as a C string
-  /// using a given encoding.
-  public func cString(using encoding: Encoding) -> [CChar]? {
-    return withExtendedLifetime(_ns) {
-      (s: NSString) -> [CChar]? in
-      _persistCString(s.cString(using: encoding.rawValue))
-    }
-  }
-
-  // - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
-  //
-  // - (NSData *)
-  //     dataUsingEncoding:(NSStringEncoding)encoding
-  //     allowLossyConversion:(BOOL)flag
-
-  /// Returns a `Data` containing a representation of
-  /// the `String` encoded using a given encoding.
-  public func data(
-    using encoding: Encoding,
-    allowLossyConversion: Bool = false
-  ) -> Data? {
-    return _ns.data(
-      using: encoding.rawValue,
-      allowLossyConversion: allowLossyConversion)
-  }
-
-  // @property NSString* decomposedStringWithCanonicalMapping;
-
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form D.
-  public var decomposedStringWithCanonicalMapping: String {
-    return _ns.decomposedStringWithCanonicalMapping
-  }
-
-  // @property NSString* decomposedStringWithCompatibilityMapping;
-
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form KD.
-  public var decomposedStringWithCompatibilityMapping: String {
-    return _ns.decomposedStringWithCompatibilityMapping
-  }
-
-  //===--- Importing Foundation should not affect String printing ---------===//
-  // Therefore, we're not exposing this:
-  //
-  //   @property NSString* description
-
-
-  //===--- Omitted for consistency with API review results 5/20/2014 -----===//
-  // @property double doubleValue;
-
-  // - (void)
-  //     enumerateLinesUsing:(void (^)(NSString *line, BOOL *stop))block
-
-  /// Enumerates all the lines in a string.
-  public func enumerateLines(
-    invoking body: @escaping (_ line: String, _ stop: inout Bool) -> Void
-  ) {
-    _ns.enumerateLines {
-      (line: String, stop: UnsafeMutablePointer<ObjCBool>)
-    in
-      var stop_ = false
-      body(line, &stop_)
-      if stop_ {
-        stop.pointee = true
-      }
-    }
-  }
-
-
-  // - (void)
-  //     enumerateSubstringsInRange:(NSRange)range
-  //     options:(NSStringEnumerationOptions)opts
-  //     usingBlock:(
-  //       void (^)(
-  //         NSString *substring,
-  //         NSRange substringRange,
-  //         NSRange enclosingRange,
-  //         BOOL *stop)
-  //       )block
-
-  /// Enumerates the substrings of the specified type in the
-  /// specified range of the string.
-  public func enumerateSubstrings(
-    in range: Range<Index>,
-    options opts: EnumerationOptions = [],
-    _ body: @escaping (
-      _ substring: String?, _ substringRange: Range<Index>,
-      _ enclosingRange: Range<Index>, inout Bool
-    ) -> Void
-  ) {
-    _ns.enumerateSubstrings(in: _toNSRange(range), options: opts) {
-      var stop_ = false
-
-      body($0,
-        self._range($1),
-        self._range($2),
-        &stop_)
-
-      if stop_ {
-        UnsafeMutablePointer($3).pointee = true
-      }
-    }
-  }
-
-  // @property NSStringEncoding fastestEncoding;
-
-  /// Returns the fastest encoding to which the `String` may be
-  /// converted without loss of information.
-  public var fastestEncoding: Encoding {
-    return Encoding(rawValue: _ns.fastestEncoding)
-  }
-
-  // - (const char *)fileSystemRepresentation
-
-  /// Returns a file system-specific representation of the `String`.
-  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
-  public var fileSystemRepresentation: [CChar] {
-    return _persistCString(_ns.fileSystemRepresentation)!
-  }
-
-  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
-  // @property float floatValue;
-
-  // - (BOOL)
-  //     getBytes:(void *)buffer
-  //     maxLength:(NSUInteger)maxBufferCount
-  //     usedLength:(NSUInteger*)usedBufferCount
-  //     encoding:(NSStringEncoding)encoding
-  //     options:(StringEncodingConversionOptions)options
-  //     range:(NSRange)range
-  //     remainingRange:(NSRangePointer)leftover
-
-  /// Writes the given `range` of characters into `buffer` in a given
-  /// `encoding`, without any allocations.  Does not NULL-terminate.
-  ///
-  /// - Parameter buffer: A buffer into which to store the bytes from
-  ///   the receiver. The returned bytes are not NUL-terminated.
-  ///
-  /// - Parameter maxBufferCount: The maximum number of bytes to write
-  ///   to buffer.
-  ///
-  /// - Parameter usedBufferCount: The number of bytes used from
-  ///   buffer. Pass `nil` if you do not need this value.
-  ///
-  /// - Parameter encoding: The encoding to use for the returned bytes.
-  ///
-  /// - Parameter options: A mask to specify options to use for
-  ///   converting the receiver's contents to `encoding` (if conversion
-  ///   is necessary).
-  ///
-  /// - Parameter range: The range of characters in the receiver to get.
-  ///
-  /// - Parameter leftover: The remaining range. Pass `nil` If you do
-  ///   not need this value.
-  ///
-  /// - Returns: `true` iff some characters were converted.
-  ///
-  /// - Note: Conversion stops when the buffer fills or when the
-  ///   conversion isn't possible due to the chosen encoding.
-  ///
-  /// - Note: will get a maximum of `min(buffer.count, maxLength)` bytes.
-  public func getBytes(
-    _ buffer: inout [UInt8],
-    maxLength maxBufferCount: Int,
-    usedLength usedBufferCount: UnsafeMutablePointer<Int>,
-    encoding: Encoding,
-    options: EncodingConversionOptions = [],
-    range: Range<Index>,
-    remaining leftover: UnsafeMutablePointer<Range<Index>>
-  ) -> Bool {
-    return _withOptionalOutParameter(leftover) {
-      self._ns.getBytes(
-        &buffer,
-        maxLength: min(buffer.count, maxBufferCount),
-        usedLength: usedBufferCount,
-        encoding: encoding.rawValue,
-        options: options,
-        range: _toNSRange(range),
-        remaining: $0)
-    }
-  }
-
-  // - (BOOL)
-  //     getCString:(char *)buffer
-  //     maxLength:(NSUInteger)maxBufferCount
-  //     encoding:(NSStringEncoding)encoding
-
-  /// Converts the `String`'s content to a given encoding and
-  /// stores them in a buffer.
-  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
-  public func getCString(
-    _ buffer: inout [CChar], maxLength: Int, encoding: Encoding
-  ) -> Bool {
-    return _ns.getCString(&buffer, maxLength: min(buffer.count, maxLength),
-                          encoding: encoding.rawValue)
-  }
-
-  // - (BOOL)
-  //     getFileSystemRepresentation:(char *)buffer
-  //     maxLength:(NSUInteger)maxLength
-
-  /// Interprets the `String` as a system-independent path and
-  /// fills a buffer with a C-string in a format and encoding suitable
-  /// for use with file-system calls.
-  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
-  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
-  public func getFileSystemRepresentation(
-    _ buffer: inout [CChar], maxLength: Int) -> Bool {
-    return _ns.getFileSystemRepresentation(
-      &buffer, maxLength: min(buffer.count, maxLength))
-  }
-
-  // - (void)
-  //     getLineStart:(NSUInteger *)startIndex
-  //     end:(NSUInteger *)lineEndIndex
-  //     contentsEnd:(NSUInteger *)contentsEndIndex
-  //     forRange:(NSRange)aRange
-
-  /// Returns by reference the beginning of the first line and
-  /// the end of the last line touched by the given range.
-  public func getLineStart(
-    _ start: UnsafeMutablePointer<Index>,
-    end: UnsafeMutablePointer<Index>,
-    contentsEnd: UnsafeMutablePointer<Index>,
-    for range: Range<Index>
-  ) {
-    _withOptionalOutParameter(start) {
-      start in self._withOptionalOutParameter(end) {
-        end in self._withOptionalOutParameter(contentsEnd) {
-          contentsEnd in self._ns.getLineStart(
-            start, end: end,
-            contentsEnd: contentsEnd,
-            for: _toNSRange(range))
-        }
-      }
-    }
-  }
-
-  // - (void)
-  //     getParagraphStart:(NSUInteger *)startIndex
-  //     end:(NSUInteger *)endIndex
-  //     contentsEnd:(NSUInteger *)contentsEndIndex
-  //     forRange:(NSRange)aRange
-
-  /// Returns by reference the beginning of the first paragraph
-  /// and the end of the last paragraph touched by the given range.
-  public func getParagraphStart(
-    _ start: UnsafeMutablePointer<Index>,
-    end: UnsafeMutablePointer<Index>,
-    contentsEnd: UnsafeMutablePointer<Index>,
-    for range: Range<Index>
-  ) {
-    _withOptionalOutParameter(start) {
-      start in self._withOptionalOutParameter(end) {
-        end in self._withOptionalOutParameter(contentsEnd) {
-          contentsEnd in self._ns.getParagraphStart(
-            start, end: end,
-            contentsEnd: contentsEnd,
-            for: _toNSRange(range))
-        }
-      }
-    }
-  }
-
-  // - (NSUInteger)hash
-
-  /// An unsigned integer that can be used as a hash table address.
-  public var hash: Int {
-    return _ns.hash
-  }
-
+extension String {
   //===--- Already provided by String's core ------------------------------===//
   // - (instancetype)init
 
@@ -644,13 +187,18 @@
   //     length:(NSUInteger)length
   //     encoding:(NSStringEncoding)encoding
 
-  /// Produces an initialized `NSString` object equivalent to the given
-  /// `bytes` interpreted in the given `encoding`.
+  /// Creates a new string equivalent to the given bytes interpreted in the
+  /// specified encoding.
+  ///
+  /// - Parameters:
+  ///   - bytes: A sequence of bytes to interpret using `encoding`.
+  ///   - encoding: The ecoding to use to interpret `bytes`.
   public init? <S: Sequence>(bytes: S, encoding: Encoding)
     where S.Iterator.Element == UInt8 {
     let byteArray = Array(bytes)
     if let ns = NSString(
       bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
+
       self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
@@ -663,10 +211,11 @@
   //     encoding:(NSStringEncoding)encoding
   //     freeWhenDone:(BOOL)flag
 
-  /// Produces an initialized `String` object that contains a
-  /// given number of bytes from a given buffer of bytes interpreted
-  /// in a given encoding, and optionally frees the buffer.  WARNING:
-  /// this initializer is not memory-safe!
+  /// Creates a new string that contains the specified number of bytes from the
+  /// given buffer, interpreted in the specified encoding, and optionally
+  /// frees the buffer.
+  ///
+  /// - Warning: This initializer is not memory-safe!
   public init?(
     bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int,
     encoding: Encoding, freeWhenDone flag: Bool
@@ -674,6 +223,7 @@
     if let ns = NSString(
       bytesNoCopy: bytes, length: length, encoding: encoding.rawValue,
       freeWhenDone: flag) {
+
       self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
@@ -685,9 +235,8 @@
   //     initWithCharacters:(const unichar *)characters
   //     length:(NSUInteger)length
 
-  /// Returns an initialized `String` object that contains a
-  /// given number of characters from a given array of Unicode
-  /// characters.
+  /// Creates a new string that contains the specified number of characters
+  /// from the given C array of Unicode characters.
   public init(
     utf16CodeUnits: UnsafePointer<unichar>,
     count: Int
@@ -700,8 +249,8 @@
   //     length:(NSUInteger)length
   //     freeWhenDone:(BOOL)flag
 
-  /// Returns an initialized `String` object that contains a given
-  /// number of characters from a given array of UTF-16 Code Units
+  /// Creates a new string that contains the specified number of characters
+  /// from the given C array of UTF-16 code units.
   public init(
     utf16CodeUnitsNoCopy: UnsafePointer<unichar>,
     count: Int,
@@ -813,9 +362,9 @@
       return nil
     }
   }
-  
+
   // FIXME: handle optional locale with default arguments
-  
+
   // - (instancetype)
   //     initWithData:(NSData *)data
   //     encoding:(NSStringEncoding)encoding
@@ -826,7 +375,7 @@
     guard let s = NSString(data: data, encoding: encoding.rawValue) else { return nil }
     self = String._unconditionallyBridgeFromObjectiveC(s)
   }
-  
+
   // - (instancetype)initWithFormat:(NSString *)format, ...
 
   /// Returns a `String` object initialized by using a given
@@ -865,83 +414,461 @@
   /// format string as a template into which the remaining argument
   /// values are substituted according to given locale information.
   public init(format: String, locale: Locale?, arguments: [CVarArg]) {
+#if DEPLOYMENT_RUNTIME_SWIFT
     self = withVaList(arguments) {
       String._unconditionallyBridgeFromObjectiveC(
         NSString(format: format, locale: locale?._bridgeToObjectiveC(), arguments: $0)
       )
     }
+#else
+    self = withVaList(arguments) {
+      NSString(format: format, locale: locale, arguments: $0) as String
+    }
+#endif
   }
 
-  //===--- Already provided by core Swift ---------------------------------===//
-  // - (instancetype)initWithString:(NSString *)aString
+}
 
-  //===--- Initializers that can fail dropped for factory functions -------===//
-  // - (instancetype)initWithUTF8String:(const char *)bytes
+extension StringProtocol where Index == String.Index {
+  //===--- Bridging Helpers -----------------------------------------------===//
+  //===--------------------------------------------------------------------===//
 
-  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
-  // @property NSInteger integerValue;
-  // @property Int intValue;
-
-  //===--- Omitted by apparent agreement during API review 5/20/2014 ------===//
-  // @property BOOL absolutePath;
-  // - (BOOL)isEqualToString:(NSString *)aString
-
-  //===--- Kept for consistency with API review results 5/20/2014 ---------===//
-  // We decided to keep pathWithComponents, so keeping this too
-  // @property NSString lastPathComponent;
-
-  /// Returns the last path component of the `String`.
-  @available(*, unavailable, message: "Use lastPathComponent on URL instead.")
-  public var lastPathComponent: String {
-    return _ns.lastPathComponent
+  /// The corresponding `NSString` - a convenience for bridging code.
+  // FIXME(strings): There is probably a better way to bridge Self to NSString
+  var _ns: NSString {
+    return self._ephemeralString._bridgeToObjectiveC()
   }
 
-  //===--- Renamed by agreement during API review 5/20/2014 ---------------===//
-  // @property NSUInteger length;
+  /// Return an `Index` corresponding to the given offset in our UTF-16
+  /// representation.
+  func _index(_ utf16Index: Int) -> Index {
+    return Index(encodedOffset: utf16Index)
+  }
 
-  /// Returns the number of Unicode characters in the `String`.
-  @available(*, unavailable,
-    message: "Take the count of a UTF-16 view instead, i.e. str.utf16.count")
-  public var utf16Count: Int {
-    return _ns.length
+  /// Return a `Range<Index>` corresponding to the given `NSRange` of
+  /// our UTF-16 representation.
+  func _range(_ r: NSRange) -> Range<Index> {
+    return _index(r.location)..<_index(r.location + r.length)
+  }
+
+  /// Return a `Range<Index>?` corresponding to the given `NSRange` of
+  /// our UTF-16 representation.
+  func _optionalRange(_ r: NSRange) -> Range<Index>? {
+    if r.location == NSNotFound {
+      return nil
+    }
+    return _range(r)
+  }
+
+  /// Invoke `body` on an `Int` buffer.  If `index` was converted from
+  /// non-`nil`, convert the buffer to an `Index` and write it into the
+  /// memory referred to by `index`
+  func _withOptionalOutParameter<Result>(
+    _ index: UnsafeMutablePointer<Index>?,
+    _ body: (UnsafeMutablePointer<Int>?) -> Result
+  ) -> Result {
+    var utf16Index: Int = 0
+    let result = (index != nil ? body(&utf16Index) : body(nil))
+    index?.pointee = _index(utf16Index)
+    return result
+  }
+
+  /// Invoke `body` on an `NSRange` buffer.  If `range` was converted
+  /// from non-`nil`, convert the buffer to a `Range<Index>` and write
+  /// it into the memory referred to by `range`
+  func _withOptionalOutParameter<Result>(
+    _ range: UnsafeMutablePointer<Range<Index>>?,
+    _ body: (UnsafeMutablePointer<NSRange>?) -> Result
+  ) -> Result {
+    var nsRange = NSRange(location: 0, length: 0)
+    let result = (range != nil ? body(&nsRange) : body(nil))
+    range?.pointee = self._range(nsRange)
+    return result
+  }
+
+  //===--- Instance Methods/Properties-------------------------------------===//
+  //===--------------------------------------------------------------------===//
+
+  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
+  // @property BOOL boolValue;
+
+  // - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
+
+  /// Returns a Boolean value that indicates whether the string can be
+  /// converted to the specified encoding without loss of information.
+  ///
+  /// - Parameter encoding: A string encoding.
+  /// - Returns: `true` if the string can be encoded in `encoding` without loss
+  ///   of information; otherwise, `false`.
+  public func canBeConverted(to encoding: String.Encoding) -> Bool {
+    return _ns.canBeConverted(to: encoding.rawValue)
+  }
+
+  // @property NSString* capitalizedString
+
+  /// A copy of the string with each word changed to its corresponding
+  /// capitalized spelling.
+  ///
+  /// This property performs the canonical (non-localized) mapping. It is
+  /// suitable for programming operations that require stable results not
+  /// depending on the current locale.
+  ///
+  /// A capitalized string is a string with the first character in each word
+  /// changed to its corresponding uppercase value, and all remaining
+  /// characters set to their corresponding lowercase values. A "word" is any
+  /// sequence of characters delimited by spaces, tabs, or line terminators.
+  /// Some common word delimiting punctuation isn't considered, so this
+  /// property may not generally produce the desired results for multiword
+  /// strings. See the `getLineStart(_:end:contentsEnd:for:)` method for
+  /// additional information.
+  ///
+  /// Case transformations aren’t guaranteed to be symmetrical or to produce
+  /// strings of the same lengths as the originals.
+  public var capitalized: String {
+    return _ns.capitalized as String
+  }
+
+  // @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
+
+  /// A capitalized representation of the string that is produced
+  /// using the current locale.
+  @available(OSX 10.11, iOS 9.0, *)
+  public var localizedCapitalized: String {
+    return _ns.localizedCapitalized
+  }
+
+  // - (NSString *)capitalizedStringWithLocale:(Locale *)locale
+
+  /// Returns a capitalized representation of the string
+  /// using the specified locale.
+  public func capitalized(with locale: Locale?) -> String {
+    return _ns.capitalized(with: locale) as String
+  }
+
+  // - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
+
+  /// Returns the result of invoking `compare:options:` with
+  /// `NSCaseInsensitiveSearch` as the only option.
+  public func caseInsensitiveCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.caseInsensitiveCompare(aString._ephemeralString)
+  }
+
+  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
+  // - (unichar)characterAtIndex:(NSUInteger)index
+  //
+  // We have a different meaning for "Character" in Swift, and we are
+  // trying not to expose error-prone UTF-16 integer indexes
+
+  // - (NSString *)
+  //     commonPrefixWithString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+
+  /// Returns a string containing characters this string and the
+  /// given string have in common, starting from the beginning of each
+  /// up to the first characters that aren't equivalent.
+  public func commonPrefix<
+    T : StringProtocol
+  >(with aString: T, options: String.CompareOptions = []) -> String {
+    return _ns.commonPrefix(with: aString._ephemeralString, options: options)
+  }
+
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //     range:(NSRange)range
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //     range:(NSRange)range locale:(id)locale
+
+  /// Compares the string using the specified options and
+  /// returns the lexical ordering for the range.
+  public func compare<T : StringProtocol>(
+    _ aString: T,
+    options mask: String.CompareOptions = [],
+    range: Range<Index>? = nil,
+    locale: Locale? = nil
+  ) -> ComparisonResult {
+    // According to Ali Ozer, there may be some real advantage to
+    // dispatching to the minimal selector for the supplied options.
+    // So let's do that; the switch should compile away anyhow.
+    let aString = aString._ephemeralString
+    return locale != nil ? _ns.compare(
+      aString,
+      options: mask,
+      range: _toNSRange(
+        range ?? startIndex..<endIndex
+      ),
+      locale: locale?._bridgeToObjectiveC()
+    )
+
+    : range != nil ? _ns.compare(
+      aString,
+      options: mask,
+      range: _toNSRange(range!)
+    )
+
+    : !mask.isEmpty ? _ns.compare(aString, options: mask)
+
+    : _ns.compare(aString)
+  }
+
+  // - (NSUInteger)
+  //     completePathIntoString:(NSString **)outputName
+  //     caseSensitive:(BOOL)flag
+  //     matchesIntoArray:(NSArray **)outputArray
+  //     filterTypes:(NSArray *)filterTypes
+
+  /// Interprets the string as a path in the file system and
+  /// attempts to perform filename completion, returning a numeric
+  /// value that indicates whether a match was possible, and by
+  /// reference the longest path that matches the string.
+  ///
+  /// - Returns: The actual number of matching paths.
+  public func completePath(
+    into outputName: UnsafeMutablePointer<String>? = nil,
+    caseSensitive: Bool,
+    matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
+    filterTypes: [String]? = nil
+  ) -> Int {
+#if DEPLOYMENT_RUNTIME_SWIFT
+    var outputNamePlaceholder: String?
+    var outputArrayPlaceholder = [String]()
+    let res = self._ns.completePath(
+        into: &outputNamePlaceholder,
+        caseSensitive: caseSensitive,
+        matchesInto: &outputArrayPlaceholder,
+        filterTypes: filterTypes
+    )
+    if let n = outputNamePlaceholder {
+        outputName?.pointee = n
+    } else {
+        outputName?.pointee = ""
+    }
+    outputArray?.pointee = outputArrayPlaceholder
+    return res
+#else // DEPLOYMENT_RUNTIME_SWIFT
+    var nsMatches: NSArray?
+    var nsOutputName: NSString?
+
+    let result: Int = outputName._withNilOrAddress(of: &nsOutputName) {
+      outputName in outputArray._withNilOrAddress(of: &nsMatches) {
+        outputArray in
+        // FIXME: completePath(...) is incorrectly annotated as requiring
+        // non-optional output parameters. rdar://problem/25494184
+        let outputNonOptionalName = unsafeBitCast(
+          outputName, to: AutoreleasingUnsafeMutablePointer<NSString?>.self)
+        let outputNonOptionalArray = unsafeBitCast(
+          outputArray, to: AutoreleasingUnsafeMutablePointer<NSArray?>.self)
+        return self._ns.completePath(
+          into: outputNonOptionalName,
+          caseSensitive: caseSensitive,
+          matchesInto: outputNonOptionalArray,
+          filterTypes: filterTypes
+        )
+      }
+    }
+
+    if let matches = nsMatches {
+      // Since this function is effectively a bridge thunk, use the
+      // bridge thunk semantics for the NSArray conversion
+      outputArray?.pointee = matches as! [String]
+    }
+
+    if let n = nsOutputName {
+      outputName?.pointee = n as String
+    }
+    return result
+#endif // DEPLOYMENT_RUNTIME_SWIFT
+  }
+
+  // - (NSArray *)
+  //     componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
+
+  /// Returns an array containing substrings from the string
+  /// that have been divided by characters in the given set.
+  public func components(separatedBy separator: CharacterSet) -> [String] {
+    return _ns.components(separatedBy: separator)
+  }
+
+  // - (NSArray *)componentsSeparatedByString:(NSString *)separator
+
+  /// Returns an array containing substrings from the string that have been
+  /// divided by the given separator.
+  ///
+  /// The substrings in the resulting array appear in the same order as the
+  /// original string. Adjacent occurrences of the separator string produce
+  /// empty strings in the result. Similarly, if the string begins or ends
+  /// with the separator, the first or last substring, respectively, is empty.
+  /// The following example shows this behavior:
+  ///
+  ///     let list1 = "Karin, Carrie, David"
+  ///     let items1 = list1.components(separatedBy: ", ")
+  ///     // ["Karin", "Carrie", "David"]
+  ///
+  ///     // Beginning with the separator:
+  ///     let list2 = ", Norman, Stanley, Fletcher"
+  ///     let items2 = list2.components(separatedBy: ", ")
+  ///     // ["", "Norman", "Stanley", "Fletcher"
+  ///
+  /// If the list has no separators, the array contains only the original
+  /// string itself.
+  ///
+  ///     let name = "Karin"
+  ///     let list = name.components(separatedBy: ", ")
+  ///     // ["Karin"]
+  ///
+  /// - Parameter separator: The separator string.
+  /// - Returns: An array containing substrings that have been divided from the
+  ///   string using `separator`.
+  // FIXME(strings): now when String conforms to Collection, this can be
+  //   replaced by split(separator:maxSplits:omittingEmptySubsequences:)
+  public func components<
+    T : StringProtocol
+  >(separatedBy separator: T) -> [String] {
+    return _ns.components(separatedBy: separator._ephemeralString)
+  }
+
+  // - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
+
+  /// Returns a representation of the string as a C string
+  /// using a given encoding.
+  public func cString(using encoding: String.Encoding) -> [CChar]? {
+    return withExtendedLifetime(_ns) {
+      (s: NSString) -> [CChar]? in
+      _persistCString(s.cString(using: encoding.rawValue))
+    }
+  }
+
+  // - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  //
+  // - (NSData *)
+  //     dataUsingEncoding:(NSStringEncoding)encoding
+  //     allowLossyConversion:(BOOL)flag
+
+  /// Returns a `Data` containing a representation of
+  /// the `String` encoded using a given encoding.
+  public func data(
+    using encoding: String.Encoding,
+    allowLossyConversion: Bool = false
+  ) -> Data? {
+    return _ns.data(
+      using: encoding.rawValue,
+      allowLossyConversion: allowLossyConversion)
+  }
+
+  // @property NSString* decomposedStringWithCanonicalMapping;
+
+  /// A string created by normalizing the string's contents using Form D.
+  public var decomposedStringWithCanonicalMapping: String {
+    return _ns.decomposedStringWithCanonicalMapping
+  }
+
+  // @property NSString* decomposedStringWithCompatibilityMapping;
+
+  /// A string created by normalizing the string's contents using Form KD.
+  public var decomposedStringWithCompatibilityMapping: String {
+    return _ns.decomposedStringWithCompatibilityMapping
+  }
+
+  //===--- Importing Foundation should not affect String printing ---------===//
+  // Therefore, we're not exposing this:
+  //
+  //   @property NSString* description
+
+
+  //===--- Omitted for consistency with API review results 5/20/2014 -----===//
+  // @property double doubleValue;
+
+  // - (void)
+  //     enumerateLinesUsing:(void (^)(NSString *line, BOOL *stop))block
+
+  /// Enumerates all the lines in a string.
+  public func enumerateLines(
+    invoking body: @escaping (_ line: String, _ stop: inout Bool) -> Void
+  ) {
+    _ns.enumerateLines {
+      (line: String, stop: UnsafeMutablePointer<ObjCBool>)
+    in
+      var stop_ = false
+      body(line, &stop_)
+      if stop_ {
+        stop.pointee = true
+      }
+    }
+  }
+
+  // @property NSStringEncoding fastestEncoding;
+
+  /// The fastest encoding to which the string can be converted without loss
+  /// of information.
+  public var fastestEncoding: String.Encoding {
+    return String.Encoding(rawValue: _ns.fastestEncoding)
+  }
+
+  // - (BOOL)
+  //     getCString:(char *)buffer
+  //     maxLength:(NSUInteger)maxBufferCount
+  //     encoding:(NSStringEncoding)encoding
+
+  /// Converts the `String`'s content to a given encoding and
+  /// stores them in a buffer.
+  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
+  public func getCString(
+    _ buffer: inout [CChar], maxLength: Int, encoding: String.Encoding
+  ) -> Bool {
+    return _ns.getCString(&buffer,
+                          maxLength: Swift.min(buffer.count, maxLength),
+                          encoding: encoding.rawValue)
+  }
+
+  // - (NSUInteger)hash
+
+  /// An unsigned integer that can be used as a hash table address.
+  public var hash: Int {
+    return _ns.hash
   }
 
   // - (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)enc
 
   /// Returns the number of bytes required to store the
   /// `String` in a given encoding.
-  public func lengthOfBytes(using encoding: Encoding) -> Int {
+  public func lengthOfBytes(using encoding: String.Encoding) -> Int {
     return _ns.lengthOfBytes(using: encoding.rawValue)
   }
 
-  // - (NSRange)lineRangeForRange:(NSRange)aRange
-
-  /// Returns the range of characters representing the line or lines
-  /// containing a given range.
-  public func lineRange(for aRange: Range<Index>) -> Range<Index> {
-    return _range(_ns.lineRange(for: _toNSRange(aRange)))
-  }
-
   // - (NSComparisonResult)localizedCaseInsensitiveCompare:(NSString *)aString
 
-  /// Compares the string and a given string using a
-  /// case-insensitive, localized, comparison.
+  /// Compares the string and the given string using a case-insensitive,
+  /// localized, comparison.
   public
-  func localizedCaseInsensitiveCompare(_ aString: String) -> ComparisonResult {
-    return _ns.localizedCaseInsensitiveCompare(aString)
+  func localizedCaseInsensitiveCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.localizedCaseInsensitiveCompare(aString._ephemeralString)
   }
 
   // - (NSComparisonResult)localizedCompare:(NSString *)aString
 
-  /// Compares the string and a given string using a localized
-  /// comparison.
-  public func localizedCompare(_ aString: String) -> ComparisonResult {
-    return _ns.localizedCompare(aString)
+  /// Compares the string and the given string using a localized comparison.
+  public func localizedCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.localizedCompare(aString._ephemeralString)
   }
 
-  /// Compares strings as sorted by the Finder.
-  public func localizedStandardCompare(_ string: String) -> ComparisonResult {
-    return _ns.localizedStandardCompare(string)
+  /// Compares the string and the given string as sorted by the Finder.
+  public func localizedStandardCompare<
+    T : StringProtocol
+  >(_ string: T) -> ComparisonResult {
+    return _ns.localizedStandardCompare(string._ephemeralString)
   }
 
   //===--- Omitted for consistency with API review results 5/20/2014 ------===//
@@ -951,6 +878,7 @@
 
   /// A lowercase version of the string that is produced using the current
   /// locale.
+  @available(OSX 10.11, iOS 9.0, *)
   public var localizedLowercase: String {
     return _ns.localizedLowercase
   }
@@ -969,53 +897,25 @@
   /// Returns the maximum number of bytes needed to store the
   /// `String` in a given encoding.
   public
-  func maximumLengthOfBytes(using encoding: Encoding) -> Int {
+  func maximumLengthOfBytes(using encoding: String.Encoding) -> Int {
     return _ns.maximumLengthOfBytes(using: encoding.rawValue)
   }
 
-  // - (NSRange)paragraphRangeForRange:(NSRange)aRange
-
-  /// Returns the range of characters representing the
-  /// paragraph or paragraphs containing a given range.
-  public func paragraphRange(for aRange: Range<Index>) -> Range<Index> {
-    return _range(_ns.paragraphRange(for: _toNSRange(aRange)))
-  }
-
-  // @property NSArray* pathComponents
-
-  /// Returns an array of NSString objects containing, in
-  /// order, each path component of the `String`.
-  @available(*, unavailable, message: "Use pathComponents on URL instead.")
-  public var pathComponents: [String] {
-    return _ns.pathComponents
-  }
-
-  // @property NSString* pathExtension;
-
-  /// Interprets the `String` as a path and returns the
-  /// `String`'s extension, if any.
-  @available(*, unavailable, message: "Use pathExtension on URL instead.")
-  public var pathExtension: String {
-    return _ns.pathExtension
-  }
-
   // @property NSString* precomposedStringWithCanonicalMapping;
 
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form C.
+  /// A string created by normalizing the string's contents using Form C.
   public var precomposedStringWithCanonicalMapping: String {
     return _ns.precomposedStringWithCanonicalMapping
   }
 
   // @property NSString * precomposedStringWithCompatibilityMapping;
 
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form KC.
+  /// A string created by normalizing the string's contents using Form KC.
   public var precomposedStringWithCompatibilityMapping: String {
     return _ns.precomposedStringWithCompatibilityMapping
   }
 
-#if false
+#if !DEPLOYMENT_RUNTIME_SWIFT
   // - (id)propertyList
 
   /// Parses the `String` as a text representation of a
@@ -1029,151 +929,41 @@
 
   /// Returns a dictionary object initialized with the keys and
   /// values found in the `String`.
-  public
-  func propertyListFromStringsFileFormat() -> [String : String] {
-    return _ns.propertyListFromStringsFileFormat()! as [NSObject : AnyObject]
-      as! [String : String]
+  public func propertyListFromStringsFileFormat() -> [String : String] {
+    return _ns.propertyListFromStringsFileFormat() as! [String : String]? ?? [:]
   }
 #endif
-    
-  // - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //
-  // - (NSRange)
-  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //     options:(StringCompareOptions)mask
-  //
-  // - (NSRange)
-  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)aRange
-
-  /// Finds and returns the range in the `String` of the first
-  /// character from a given character set found in a given range with
-  /// given options.
-  public func rangeOfCharacter(
-    from aSet: CharacterSet,
-    options mask: CompareOptions = [],
-    range aRange: Range<Index>? = nil
-  ) -> Range<Index>? {
-    return _optionalRange(
-      _ns.rangeOfCharacter(
-        from: aSet,
-        options: mask,
-        range: _toNSRange(
-          aRange ?? self.startIndex..<self.endIndex
-        )
-      )
-    )
-  }
-
-  // - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(NSUInteger)anIndex
-
-  /// Returns the range in the `String` of the composed
-  /// character sequence located at a given index.
-  public
-  func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
-    return _range(
-      _ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
-  }
-
-  // - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
-
-  /// Returns the range in the string of the composed character
-  /// sequences for a given range.
-  public func rangeOfComposedCharacterSequences(
-    for range: Range<Index>
-  ) -> Range<Index> {
-    // Theoretically, this will be the identity function.  In practice
-    // I think users will be able to observe differences in the input
-    // and output ranges due (if nothing else) to locale changes
-    return _range(
-      _ns.rangeOfComposedCharacterSequences(for: _toNSRange(range)))
-  }
-
-  // - (NSRange)rangeOfString:(NSString *)aString
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString options:(StringCompareOptions)mask
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)aRange
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)searchRange
-  //     locale:(Locale *)locale
-
-  /// Finds and returns the range of the first occurrence of a
-  /// given string within a given range of the `String`, subject to
-  /// given options, using the specified locale, if any.
-  public func range(
-    of aString: String,
-    options mask: CompareOptions = [],
-    range searchRange: Range<Index>? = nil,
-    locale: Locale? = nil
-  ) -> Range<Index>? {
-    return _optionalRange(
-      locale != nil ? _ns.range(
-        of: aString,
-        options: mask,
-        range: _toNSRange(
-          searchRange ?? self.startIndex..<self.endIndex
-        ),
-        locale: locale
-      )
-      : searchRange != nil ? _ns.range(
-        of: aString, options: mask, range: _toNSRange(searchRange!)
-      )
-      : !mask.isEmpty ? _ns.range(of: aString, options: mask)
-      : _ns.range(of: aString)
-    )
-  }
 
   // - (BOOL)localizedStandardContainsString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
 
-  /// Returns `true` if `self` contains `string`, taking the current locale
-  /// into account.
+  /// Returns a Boolean value indicating whether the string contains the given
+  /// string, taking the current locale into account.
   ///
   /// This is the most appropriate method for doing user-level string searches,
   /// similar to how searches are done generally in the system.  The search is
   /// locale-aware, case and diacritic insensitive.  The exact list of search
   /// options applied may change over time.
-  public func localizedStandardContains(_ string: String) -> Bool {
-    return _ns.localizedStandardContains(string)
-  }
-
-  // - (NSRange)localizedStandardRangeOfString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
-
-  /// Finds and returns the range of the first occurrence of a given string,
-  /// taking the current locale into account.  Returns `nil` if the string was
-  /// not found.
-  ///
-  /// This is the most appropriate method for doing user-level string searches,
-  /// similar to how searches are done generally in the system.  The search is
-  /// locale-aware, case and diacritic insensitive.  The exact list of search
-  /// options applied may change over time.
-  public func localizedStandardRange(of string: String) -> Range<Index>? {
-    return _optionalRange(_ns.localizedStandardRange(of: string))
+  @available(OSX 10.11, iOS 9.0, *)
+  public func localizedStandardContains<
+    T : StringProtocol
+  >(_ string: T) -> Bool {
+    return _ns.localizedStandardContains(string._ephemeralString)
   }
 
   // @property NSStringEncoding smallestEncoding;
 
-  /// Returns the smallest encoding to which the `String` can
-  /// be converted without loss of information.
-  public var smallestEncoding: Encoding {
-    return Encoding(rawValue: _ns.smallestEncoding)
+  /// The smallest encoding to which the string can be converted without
+  /// loss of information.
+  public var smallestEncoding: String.Encoding {
+    return String.Encoding(rawValue: _ns.smallestEncoding)
   }
 
   // - (NSString *)
   //     stringByAddingPercentEncodingWithAllowedCharacters:
   //       (NSCharacterSet *)allowedCharacters
 
-  /// Returns a new string made from the `String` by replacing
-  /// all characters not in the specified set with percent encoded
-  /// characters.
+  /// Returns a new string created by replacing all characters in the string
+  /// not in the specified set with percent encoded characters.
   public func addingPercentEncoding(
     withAllowedCharacters allowedCharacters: CharacterSet
   ) -> String? {
@@ -1193,90 +983,31 @@
 
   // - (NSString *)stringByAppendingFormat:(NSString *)format, ...
 
-  /// Returns a string made by appending to the `String` a
-  /// string constructed from a given format string and the following
-  /// arguments.
-  public func appendingFormat(
-    _ format: String, _ arguments: CVarArg...
+  /// Returns a string created by appending a string constructed from a given
+  /// format string and the following arguments.
+  public func appendingFormat<
+    T : StringProtocol
+  >(
+    _ format: T, _ arguments: CVarArg...
   ) -> String {
     return _ns.appending(
-      String(format: format, arguments: arguments))
-  }
-
-  // - (NSString *)stringByAppendingPathComponent:(NSString *)aString
-
-  /// Returns a new string made by appending to the `String` a given string.
-  @available(*, unavailable, message: "Use appendingPathComponent on URL instead.")
-  public func appendingPathComponent(_ aString: String) -> String {
-    return _ns.appendingPathComponent(aString)
-  }
-
-  // - (NSString *)stringByAppendingPathExtension:(NSString *)ext
-
-  /// Returns a new string made by appending to the `String` an
-  /// extension separator followed by a given extension.
-  @available(*, unavailable, message: "Use appendingPathExtension on URL instead.")
-  public func appendingPathExtension(_ ext: String) -> String? {
-    // FIXME: This method can return nil in practice, for example when self is
-    // an empty string.  OTOH, this is not documented, documentation says that
-    // it always returns a string.
-    //
-    // <rdar://problem/17902469> -[NSString stringByAppendingPathExtension] can
-    // return nil
-    return _ns.appendingPathExtension(ext)
+      String(format: format._ephemeralString, arguments: arguments))
   }
 
   // - (NSString *)stringByAppendingString:(NSString *)aString
 
-  /// Returns a new string made by appending a given string to
-  /// the `String`.
-  public func appending(_ aString: String) -> String {
-    return _ns.appending(aString)
-  }
-
-  // @property NSString* stringByDeletingLastPathComponent;
-
-  /// Returns a new string made by deleting the last path
-  /// component from the `String`, along with any final path
-  /// separator.
-  @available(*, unavailable, message: "Use deletingLastPathComponent on URL instead.")
-  public var deletingLastPathComponent: String {
-    return _ns.deletingLastPathComponent
-  }
-
-  // @property NSString* stringByDeletingPathExtension;
-
-  /// Returns a new string made by deleting the extension (if
-  /// any, and only the last) from the `String`.
-  @available(*, unavailable, message: "Use deletingPathExtension on URL instead.")
-  public var deletingPathExtension: String {
-    return _ns.deletingPathExtension
-  }
-
-  // @property NSString* stringByExpandingTildeInPath;
-
-  /// Returns a new string made by expanding the initial
-  /// component of the `String` to its full path value.
-  @available(*, unavailable, message: "Use expandingTildeInPath on NSString instead.")
-  public var expandingTildeInPath: String {
-    return _ns.expandingTildeInPath
-  }
-
-  // - (NSString *)
-  //     stringByFoldingWithOptions:(StringCompareOptions)options
-  //     locale:(Locale *)locale
-
-  @available(*, unavailable, renamed: "folding(options:locale:)")
-  public func folding(
-    _ options: CompareOptions = [], locale: Locale?
-  ) -> String {
-    return folding(options: options, locale: locale)
+  /// Returns a new string created by appending the given string.
+  // FIXME(strings): shouldn't it be deprecated in favor of `+`?
+  public func appending<
+    T : StringProtocol
+  >(_ aString: T) -> String {
+    return _ns.appending(aString._ephemeralString)
   }
 
   /// Returns a string with the given character folding options
   /// applied.
   public func folding(
-    options: CompareOptions = [], locale: Locale?
+    options: String.CompareOptions = [], locale: Locale?
   ) -> String {
     return _ns.folding(options: options, locale: locale)
   }
@@ -1288,20 +1019,23 @@
   /// Returns a new string formed from the `String` by either
   /// removing characters from the end, or by appending as many
   /// occurrences as necessary of a given pad string.
-  public func padding(
+  public func padding<
+    T : StringProtocol
+  >(
     toLength newLength: Int,
-    withPad padString: String,
+    withPad padString: T,
     startingAt padIndex: Int
   ) -> String {
     return _ns.padding(
-      toLength: newLength, withPad: padString, startingAt: padIndex)
+      toLength: newLength,
+      withPad: padString._ephemeralString,
+      startingAt: padIndex)
   }
 
   // @property NSString* stringByRemovingPercentEncoding;
 
-  /// Returns a new string made from the `String` by replacing
-  /// all percent encoded sequences with the matching UTF-8
-  /// characters.
+  /// A new string made from the string by replacing all percent encoded
+  /// sequences with the matching UTF-8 characters.
   public var removingPercentEncoding: String? {
     return _ns.removingPercentEncoding
   }
@@ -1312,10 +1046,12 @@
 
   /// Returns a new string in which the characters in a
   /// specified range of the `String` are replaced by a given string.
-  public func replacingCharacters(
-    in range: Range<Index>, with replacement: String
-  ) -> String {
-    return _ns.replacingCharacters(in: _toNSRange(range), with: replacement)
+  public func replacingCharacters<
+    T : StringProtocol, R : RangeExpression
+  >(in range: R, with replacement: T) -> String where R.Bound == Index {
+    return _ns.replacingCharacters(
+      in: _toNSRange(range.relative(to: self)),
+      with: replacement._ephemeralString)
   }
 
   // - (NSString *)
@@ -1329,43 +1065,46 @@
   //     range:(NSRange)searchRange
 
   /// Returns a new string in which all occurrences of a target
-  /// string in a specified range of the `String` are replaced by
+  /// string in a specified range of the string are replaced by
   /// another given string.
-  public func replacingOccurrences(
-    of target: String,
-    with replacement: String,
-    options: CompareOptions = [],
+  public func replacingOccurrences<
+    Target : StringProtocol,
+    Replacement : StringProtocol
+  >(
+    of target: Target,
+    with replacement: Replacement,
+    options: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil
   ) -> String {
+    let target = target._ephemeralString
+    let replacement = replacement._ephemeralString
     return (searchRange != nil) || (!options.isEmpty)
     ? _ns.replacingOccurrences(
       of: target,
       with: replacement,
       options: options,
       range: _toNSRange(
-        searchRange ?? self.startIndex..<self.endIndex
+        searchRange ?? startIndex..<endIndex
       )
     )
     : _ns.replacingOccurrences(of: target, with: replacement)
   }
 
-  // @property NSString* stringByResolvingSymlinksInPath;
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSString *)
+  //     stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
 
-  /// Returns a new string made from the `String` by resolving
-  /// all symbolic links and standardizing path.
-  @available(*, unavailable, message: "Use resolvingSymlinksInPath on URL instead.")
-  public var resolvingSymlinksInPath: String {
-    return _ns.resolvingSymlinksInPath
+  /// Returns a new string made by replacing in the `String`
+  /// all percent escapes with the matching characters as determined
+  /// by a given encoding.
+  @available(swift, deprecated: 3.0, obsoleted: 4.0,
+    message: "Use removingPercentEncoding instead, which always uses the recommended UTF-8 encoding.")
+  public func replacingPercentEscapes(
+    using encoding: String.Encoding
+  ) -> String? {
+    return _ns.replacingPercentEscapes(using: encoding.rawValue)
   }
-
-  // @property NSString* stringByStandardizingPath;
-
-  /// Returns a new string made by removing extraneous path
-  /// components from the `String`.
-  @available(*, unavailable, message: "Use standardizingPath on URL instead.")
-  public var standardizingPath: String {
-    return _ns.standardizingPath
-  }
+#endif
 
   // - (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set
 
@@ -1375,43 +1114,11 @@
     return _ns.trimmingCharacters(in: set)
   }
 
-  // - (NSArray *)stringsByAppendingPaths:(NSArray *)paths
-
-  /// Returns an array of strings made by separately appending
-  /// to the `String` each string in a given array.
-  @available(*, unavailable, message: "Map over paths with appendingPathComponent instead.")
-  public func strings(byAppendingPaths paths: [String]) -> [String] {
-    fatalError("This function is not available")
-  }
-
-  // - (NSString *)substringFromIndex:(NSUInteger)anIndex
-
-  /// Returns a new string containing the characters of the
-  /// `String` from the one at a given index to the end.
-  public func substring(from index: Index) -> String {
-    return _ns.substring(from: index.encodedOffset)
-  }
-
-  // - (NSString *)substringToIndex:(NSUInteger)anIndex
-
-  /// Returns a new string containing the characters of the
-  /// `String` up to, but not including, the one at a given index.
-  public func substring(to index: Index) -> String {
-    return _ns.substring(to: index.encodedOffset)
-  }
-
-  // - (NSString *)substringWithRange:(NSRange)aRange
-
-  /// Returns a string object containing the characters of the
-  /// `String` that lie within a given range.
-  public func substring(with aRange: Range<Index>) -> String {
-    return _ns.substring(with: _toNSRange(aRange))
-  }
-
   // @property (readonly, copy) NSString *localizedUppercaseString NS_AVAILABLE(10_11, 9_0);
 
   /// An uppercase version of the string that is produced using the current
   /// locale.
+  @available(OSX 10.11, iOS 9.0, *)
   public var localizedUppercase: String {
     return _ns.localizedUppercase as String
   }
@@ -1436,12 +1143,16 @@
 
   /// Writes the contents of the `String` to a file at a given
   /// path using a given encoding.
-  public func write(
-    toFile path: String, atomically useAuxiliaryFile:Bool,
-    encoding enc: Encoding
+  public func write<
+    T : StringProtocol
+  >(
+    toFile path: T, atomically useAuxiliaryFile: Bool,
+    encoding enc: String.Encoding
   ) throws {
-    try self._ns.write(
-      toFile: path, atomically: useAuxiliaryFile, encoding: enc.rawValue)
+    try _ns.write(
+      toFile: path._ephemeralString,
+      atomically: useAuxiliaryFile,
+      encoding: enc.rawValue)
   }
 
   // - (BOOL)
@@ -1454,23 +1165,458 @@
   /// by url using the specified encoding.
   public func write(
     to url: URL, atomically useAuxiliaryFile: Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
-    try self._ns.write(
+    try _ns.write(
       to: url, atomically: useAuxiliaryFile, encoding: enc.rawValue)
   }
 
   // - (nullable NSString *)stringByApplyingTransform:(NSString *)transform reverse:(BOOL)reverse NS_AVAILABLE(10_11, 9_0);
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
   /// Perform string transliteration.
-#if false
+  @available(OSX 10.11, iOS 9.0, *)
   public func applyingTransform(
     _ transform: StringTransform, reverse: Bool
   ) -> String? {
     return _ns.applyingTransform(transform, reverse: reverse)
   }
+
+  // - (void)
+  //     enumerateLinguisticTagsInRange:(NSRange)range
+  //     scheme:(NSString *)tagScheme
+  //     options:(LinguisticTaggerOptions)opts
+  //     orthography:(Orthography *)orthography
+  //     usingBlock:(
+  //       void (^)(
+  //         NSString *tag, NSRange tokenRange,
+  //         NSRange sentenceRange, BOOL *stop)
+  //       )block
+
+  /// Performs linguistic analysis on the specified string by
+  /// enumerating the specific range of the string, providing the
+  /// Block with the located tags.
+  public func enumerateLinguisticTags<
+    T : StringProtocol, R : RangeExpression
+  >(
+    in range: R,
+    scheme tagScheme: T,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    invoking body:
+      (String, Range<Index>, Range<Index>, inout Bool) -> Void
+  ) where R.Bound == Index {
+    let range = range.relative(to: self)
+    _ns.enumerateLinguisticTags(
+      in: _toNSRange(range),
+      scheme: tagScheme._ephemeralString,
+      options: opts,
+      orthography: orthography != nil ? orthography! : nil
+    ) {
+      var stop_ = false
+      body($0, self._range($1), self._range($2), &stop_)
+      if stop_ {
+        $3.pointee = true
+      }
+    }
+  }
 #endif
-    
+
+  // - (void)
+  //     enumerateSubstringsInRange:(NSRange)range
+  //     options:(NSStringEnumerationOptions)opts
+  //     usingBlock:(
+  //       void (^)(
+  //         NSString *substring,
+  //         NSRange substringRange,
+  //         NSRange enclosingRange,
+  //         BOOL *stop)
+  //       )block
+
+  /// Enumerates the substrings of the specified type in the specified range of
+  /// the string.
+  ///
+  /// Mutation of a string value while enumerating its substrings is not
+  /// supported. If you need to mutate a string from within `body`, convert
+  /// your string to an `NSMutableString` instance and then call the
+  /// `enumerateSubstrings(in:options:using:)` method.
+  ///
+  /// - Parameters:
+  ///   - range: The range within the string to enumerate substrings.
+  ///   - opts: Options specifying types of substrings and enumeration styles.
+  ///     If `opts` is omitted or empty, `body` is called a single time with
+  ///     the range of the string specified by `range`.
+  ///   - body: The closure executed for each substring in the enumeration. The
+  ///     closure takes four arguments:
+  ///     - The enumerated substring. If `substringNotRequired` is included in
+  ///       `opts`, this parameter is `nil` for every execution of the
+  ///       closure.
+  ///     - The range of the enumerated substring in the string that
+  ///       `enumerate(in:options:_:)` was called on.
+  ///     - The range that includes the substring as well as any separator or
+  ///       filler characters that follow. For instance, for lines,
+  ///       `enclosingRange` contains the line terminators. The enclosing
+  ///       range for the first string enumerated also contains any characters
+  ///       that occur before the string. Consecutive enclosing ranges are
+  ///       guaranteed not to overlap, and every single character in the
+  ///       enumerated range is included in one and only one enclosing range.
+  ///     - An `inout` Boolean value that the closure can use to stop the
+  ///       enumeration by setting `stop = true`.
+  public func enumerateSubstrings<
+    R : RangeExpression
+  >(
+    in range: R,
+    options opts: String.EnumerationOptions = [],
+    _ body: @escaping (
+      _ substring: String?, _ substringRange: Range<Index>,
+      _ enclosingRange: Range<Index>, inout Bool
+    ) -> Void
+  ) where R.Bound == Index {
+    _ns.enumerateSubstrings(
+      in: _toNSRange(range.relative(to: self)), options: opts) {
+      var stop_ = false
+
+      body($0,
+        self._range($1),
+        self._range($2),
+        &stop_)
+
+      if stop_ {
+        UnsafeMutablePointer($3).pointee = true
+      }
+    }
+  }
+
+  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
+  // @property float floatValue;
+
+  // - (BOOL)
+  //     getBytes:(void *)buffer
+  //     maxLength:(NSUInteger)maxBufferCount
+  //     usedLength:(NSUInteger*)usedBufferCount
+  //     encoding:(NSStringEncoding)encoding
+  //     options:(StringEncodingConversionOptions)options
+  //     range:(NSRange)range
+  //     remainingRange:(NSRangePointer)leftover
+
+  /// Writes the given `range` of characters into `buffer` in a given
+  /// `encoding`, without any allocations.  Does not NULL-terminate.
+  ///
+  /// - Parameter buffer: A buffer into which to store the bytes from
+  ///   the receiver. The returned bytes are not NUL-terminated.
+  ///
+  /// - Parameter maxBufferCount: The maximum number of bytes to write
+  ///   to buffer.
+  ///
+  /// - Parameter usedBufferCount: The number of bytes used from
+  ///   buffer. Pass `nil` if you do not need this value.
+  ///
+  /// - Parameter encoding: The encoding to use for the returned bytes.
+  ///
+  /// - Parameter options: A mask to specify options to use for
+  ///   converting the receiver's contents to `encoding` (if conversion
+  ///   is necessary).
+  ///
+  /// - Parameter range: The range of characters in the receiver to get.
+  ///
+  /// - Parameter leftover: The remaining range. Pass `nil` If you do
+  ///   not need this value.
+  ///
+  /// - Returns: `true` iff some characters were converted.
+  ///
+  /// - Note: Conversion stops when the buffer fills or when the
+  ///   conversion isn't possible due to the chosen encoding.
+  ///
+  /// - Note: will get a maximum of `min(buffer.count, maxLength)` bytes.
+  public func getBytes<
+    R : RangeExpression
+  >(
+    _ buffer: inout [UInt8],
+    maxLength maxBufferCount: Int,
+    usedLength usedBufferCount: UnsafeMutablePointer<Int>,
+    encoding: String.Encoding,
+    options: String.EncodingConversionOptions = [],
+    range: R,
+    remaining leftover: UnsafeMutablePointer<Range<Index>>
+  ) -> Bool where R.Bound == Index {
+    return _withOptionalOutParameter(leftover) {
+      self._ns.getBytes(
+        &buffer,
+        maxLength: Swift.min(buffer.count, maxBufferCount),
+        usedLength: usedBufferCount,
+        encoding: encoding.rawValue,
+        options: options,
+        range: _toNSRange(range.relative(to: self)),
+        remaining: $0)
+    }
+  }
+
+  // - (void)
+  //     getLineStart:(NSUInteger *)startIndex
+  //     end:(NSUInteger *)lineEndIndex
+  //     contentsEnd:(NSUInteger *)contentsEndIndex
+  //     forRange:(NSRange)aRange
+
+  /// Returns by reference the beginning of the first line and
+  /// the end of the last line touched by the given range.
+  public func getLineStart<
+    R : RangeExpression
+  >(
+    _ start: UnsafeMutablePointer<Index>,
+    end: UnsafeMutablePointer<Index>,
+    contentsEnd: UnsafeMutablePointer<Index>,
+    for range: R
+  ) where R.Bound == Index {
+    _withOptionalOutParameter(start) {
+      start in self._withOptionalOutParameter(end) {
+        end in self._withOptionalOutParameter(contentsEnd) {
+          contentsEnd in self._ns.getLineStart(
+            start, end: end,
+            contentsEnd: contentsEnd,
+            for: _toNSRange(range.relative(to: self)))
+        }
+      }
+    }
+  }
+
+  // - (void)
+  //     getParagraphStart:(NSUInteger *)startIndex
+  //     end:(NSUInteger *)endIndex
+  //     contentsEnd:(NSUInteger *)contentsEndIndex
+  //     forRange:(NSRange)aRange
+
+  /// Returns by reference the beginning of the first paragraph
+  /// and the end of the last paragraph touched by the given range.
+  public func getParagraphStart<
+    R : RangeExpression
+  >(
+    _ start: UnsafeMutablePointer<Index>,
+    end: UnsafeMutablePointer<Index>,
+    contentsEnd: UnsafeMutablePointer<Index>,
+    for range: R
+  ) where R.Bound == Index {
+    _withOptionalOutParameter(start) {
+      start in self._withOptionalOutParameter(end) {
+        end in self._withOptionalOutParameter(contentsEnd) {
+          contentsEnd in self._ns.getParagraphStart(
+            start, end: end,
+            contentsEnd: contentsEnd,
+            for: _toNSRange(range.relative(to: self)))
+        }
+      }
+    }
+  }
+
+  //===--- Already provided by core Swift ---------------------------------===//
+  // - (instancetype)initWithString:(NSString *)aString
+
+  //===--- Initializers that can fail dropped for factory functions -------===//
+  // - (instancetype)initWithUTF8String:(const char *)bytes
+
+  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
+  // @property NSInteger integerValue;
+  // @property Int intValue;
+
+  //===--- Omitted by apparent agreement during API review 5/20/2014 ------===//
+  // @property BOOL absolutePath;
+  // - (BOOL)isEqualToString:(NSString *)aString
+
+  // - (NSRange)lineRangeForRange:(NSRange)aRange
+
+  /// Returns the range of characters representing the line or lines
+  /// containing a given range.
+  public func lineRange<
+    R : RangeExpression
+  >(for aRange: R) -> Range<Index> where R.Bound == Index {
+    return _range(_ns.lineRange(for: _toNSRange(aRange.relative(to: self))))
+  }
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSArray *)
+  //     linguisticTagsInRange:(NSRange)range
+  //     scheme:(NSString *)tagScheme
+  //     options:(LinguisticTaggerOptions)opts
+  //     orthography:(Orthography *)orthography
+  //     tokenRanges:(NSArray**)tokenRanges
+
+  /// Returns an array of linguistic tags for the specified
+  /// range and requested tags within the receiving string.
+  public func linguisticTags<
+    T : StringProtocol, R : RangeExpression
+  >(
+    in range: R,
+    scheme tagScheme: T,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    tokenRanges: UnsafeMutablePointer<[Range<Index>]>? = nil // FIXME:Can this be nil?
+  ) -> [String] where R.Bound == Index {
+    var nsTokenRanges: NSArray?
+    let result = tokenRanges._withNilOrAddress(of: &nsTokenRanges) {
+      self._ns.linguisticTags(
+        in: _toNSRange(range.relative(to: self)),
+        scheme: tagScheme._ephemeralString,
+        options: opts,
+        orthography: orthography,
+        tokenRanges: $0) as NSArray
+    }
+
+    if nsTokenRanges != nil {
+      tokenRanges?.pointee = (nsTokenRanges! as [AnyObject]).map {
+        self._range($0.rangeValue)
+      }
+    }
+
+    return result as! [String]
+  }
+
+  // - (NSRange)paragraphRangeForRange:(NSRange)aRange
+
+  /// Returns the range of characters representing the
+  /// paragraph or paragraphs containing a given range.
+  public func paragraphRange<
+    R : RangeExpression
+  >(for aRange: R) -> Range<Index> where R.Bound == Index {
+    return _range(
+      _ns.paragraphRange(for: _toNSRange(aRange.relative(to: self))))
+  }
+#endif
+
+  // - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //
+  // - (NSRange)
+  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //     options:(StringCompareOptions)mask
+  //
+  // - (NSRange)
+  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)aRange
+
+  /// Finds and returns the range in the `String` of the first
+  /// character from a given character set found in a given range with
+  /// given options.
+  public func rangeOfCharacter(
+    from aSet: CharacterSet,
+    options mask: String.CompareOptions = [],
+    range aRange: Range<Index>? = nil
+  ) -> Range<Index>? {
+    return _optionalRange(
+      _ns.rangeOfCharacter(
+        from: aSet,
+        options: mask,
+        range: _toNSRange(
+          aRange ?? startIndex..<endIndex
+        )
+      )
+    )
+  }
+
+  // - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(NSUInteger)anIndex
+
+  /// Returns the range in the `String` of the composed
+  /// character sequence located at a given index.
+  public
+  func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
+    return _range(
+      _ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
+  }
+
+  // - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
+
+  /// Returns the range in the string of the composed character
+  /// sequences for a given range.
+  public func rangeOfComposedCharacterSequences<
+    R : RangeExpression
+  >(
+    for range: R
+  ) -> Range<Index> where R.Bound == Index {
+    // Theoretically, this will be the identity function.  In practice
+    // I think users will be able to observe differences in the input
+    // and output ranges due (if nothing else) to locale changes
+    return _range(
+      _ns.rangeOfComposedCharacterSequences(
+        for: _toNSRange(range.relative(to: self))))
+  }
+
+  // - (NSRange)rangeOfString:(NSString *)aString
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString options:(StringCompareOptions)mask
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)aRange
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)searchRange
+  //     locale:(Locale *)locale
+
+  /// Finds and returns the range of the first occurrence of a
+  /// given string within a given range of the `String`, subject to
+  /// given options, using the specified locale, if any.
+  public func range<
+    T : StringProtocol
+  >(
+    of aString: T,
+    options mask: String.CompareOptions = [],
+    range searchRange: Range<Index>? = nil,
+    locale: Locale? = nil
+  ) -> Range<Index>? {
+    let aString = aString._ephemeralString
+    return _optionalRange(
+      locale != nil ? _ns.range(
+        of: aString,
+        options: mask,
+        range: _toNSRange(
+          searchRange ?? startIndex..<endIndex
+        ),
+        locale: locale
+      )
+      : searchRange != nil ? _ns.range(
+        of: aString, options: mask, range: _toNSRange(searchRange!)
+      )
+      : !mask.isEmpty ? _ns.range(of: aString, options: mask)
+      : _ns.range(of: aString)
+    )
+  }
+
+  // - (NSRange)localizedStandardRangeOfString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
+
+  /// Finds and returns the range of the first occurrence of a given string,
+  /// taking the current locale into account.  Returns `nil` if the string was
+  /// not found.
+  ///
+  /// This is the most appropriate method for doing user-level string searches,
+  /// similar to how searches are done generally in the system.  The search is
+  /// locale-aware, case and diacritic insensitive.  The exact list of search
+  /// options applied may change over time.
+  @available(OSX 10.11, iOS 9.0, *)
+  public func localizedStandardRange<
+    T : StringProtocol
+  >(of string: T) -> Range<Index>? {
+    return _optionalRange(
+      _ns.localizedStandardRange(of: string._ephemeralString))
+  }
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSString *)
+  //     stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
+
+  /// Returns a representation of the `String` using a given
+  /// encoding to determine the percent escapes necessary to convert
+  /// the `String` into a legal URL string.
+  @available(swift, deprecated: 3.0, obsoleted: 4.0,
+    message: "Use addingPercentEncoding(withAllowedCharacters:) instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.")
+  public func addingPercentEscapes(
+    using encoding: String.Encoding
+  ) -> String? {
+    return _ns.addingPercentEscapes(using: encoding.rawValue)
+  }
+#endif
+
   //===--- From the 10.10 release notes; not in public documentation ------===//
   // No need to make these unavailable on earlier OSes, since they can
   // forward trivially to rangeOfString.
@@ -1479,44 +1625,233 @@
   /// `self` by case-sensitive, non-literal search.
   ///
   /// Equivalent to `self.rangeOfString(other) != nil`
-  public func contains(_ other: String) -> Bool {
+  public func contains<T : StringProtocol>(_ other: T) -> Bool {
     let r = self.range(of: other) != nil
     if #available(OSX 10.10, iOS 8.0, *) {
-      _sanityCheck(r == _ns.contains(other))
+      _sanityCheck(r == _ns.contains(other._ephemeralString))
     }
     return r
   }
-  
-  /// Returns `true` iff `other` is non-empty and contained within
-  /// `self` by case-insensitive, non-literal search, taking into
-  /// account the current locale.
+
+  /// Returns a Boolean value indicating whether the given string is non-empty
+  /// and contained within this string by case-insensitive, non-literal
+  /// search, taking into account the current locale.
   ///
-  /// Locale-independent case-insensitive operation, and other needs,
-  /// can be achieved by calling
-  /// `rangeOfString(_:options:_, range:_locale:_)`.
+  /// Locale-independent case-insensitive operation, and other needs, can be
+  /// achieved by calling `range(of:options:range:locale:)`.
   ///
-  /// Equivalent to
+  /// Equivalent to:
   ///
-  ///     self.rangeOf(
-  ///       other, options: .CaseInsensitiveSearch,
-  ///       locale: Locale.current) != nil
-  public func localizedCaseInsensitiveContains(_ other: String) -> Bool {
+  ///     range(of: other, options: .caseInsensitiveSearch,
+  ///           locale: Locale.current) != nil
+  public func localizedCaseInsensitiveContains<
+    T : StringProtocol
+  >(_ other: T) -> Bool {
     let r = self.range(
       of: other, options: .caseInsensitive, locale: Locale.current
     ) != nil
     if #available(OSX 10.10, iOS 8.0, *) {
-      _sanityCheck(r == _ns.localizedCaseInsensitiveContains(other))
+      _sanityCheck(r ==
+        _ns.localizedCaseInsensitiveContains(other._ephemeralString))
     }
     return r
   }
 }
 
+// Deprecated slicing
+extension StringProtocol where Index == String.Index {
+  // - (NSString *)substringFromIndex:(NSUInteger)anIndex
+
+  /// Returns a new string containing the characters of the
+  /// `String` from the one at a given index to the end.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript with a 'partial range from' operator.")
+  public func substring(from index: Index) -> String {
+    return _ns.substring(from: index.encodedOffset)
+  }
+
+  // - (NSString *)substringToIndex:(NSUInteger)anIndex
+
+  /// Returns a new string containing the characters of the
+  /// `String` up to, but not including, the one at a given index.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript with a 'partial range upto' operator.")
+  public func substring(to index: Index) -> String {
+    return _ns.substring(to: index.encodedOffset)
+  }
+
+  // - (NSString *)substringWithRange:(NSRange)aRange
+
+  /// Returns a string object containing the characters of the
+  /// `String` that lie within a given range.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript.")
+  public func substring(with aRange: Range<Index>) -> String {
+    return _ns.substring(with: _toNSRange(aRange))
+  }
+}
+
+extension StringProtocol {
+  // - (const char *)fileSystemRepresentation
+
+  /// Returns a file system-specific representation of the `String`.
+  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
+  public var fileSystemRepresentation: [CChar] {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (BOOL)
+  //     getFileSystemRepresentation:(char *)buffer
+  //     maxLength:(NSUInteger)maxLength
+
+  /// Interprets the `String` as a system-independent path and
+  /// fills a buffer with a C-string in a format and encoding suitable
+  /// for use with file-system calls.
+  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
+  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
+  public func getFileSystemRepresentation(
+    _ buffer: inout [CChar], maxLength: Int) -> Bool {
+    fatalError("unavailable function can't be called")
+  }
+
+  //===--- Kept for consistency with API review results 5/20/2014 ---------===//
+  // We decided to keep pathWithComponents, so keeping this too
+  // @property NSString lastPathComponent;
+
+  /// Returns the last path component of the `String`.
+  @available(*, unavailable, message: "Use lastPathComponent on URL instead.")
+  public var lastPathComponent: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  //===--- Renamed by agreement during API review 5/20/2014 ---------------===//
+  // @property NSUInteger length;
+
+  /// Returns the number of Unicode characters in the `String`.
+  @available(*, unavailable,
+    message: "Take the count of a UTF-16 view instead, i.e. str.utf16.count")
+  public var utf16Count: Int {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSArray* pathComponents
+
+  /// Returns an array of NSString objects containing, in
+  /// order, each path component of the `String`.
+  @available(*, unavailable, message: "Use pathComponents on URL instead.")
+  public var pathComponents: [String] {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* pathExtension;
+
+  /// Interprets the `String` as a path and returns the
+  /// `String`'s extension, if any.
+  @available(*, unavailable, message: "Use pathExtension on URL instead.")
+  public var pathExtension: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString *stringByAbbreviatingWithTildeInPath;
+
+  /// Returns a new string that replaces the current home
+  /// directory portion of the current path with a tilde (`~`)
+  /// character.
+  @available(*, unavailable, message: "Use abbreviatingWithTildeInPath on NSString instead.")
+  public var abbreviatingWithTildeInPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)stringByAppendingPathComponent:(NSString *)aString
+
+  /// Returns a new string made by appending to the `String` a given string.
+  @available(*, unavailable, message: "Use appendingPathComponent on URL instead.")
+  public func appendingPathComponent(_ aString: String) -> String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)stringByAppendingPathExtension:(NSString *)ext
+
+  /// Returns a new string made by appending to the `String` an
+  /// extension separator followed by a given extension.
+  @available(*, unavailable, message: "Use appendingPathExtension on URL instead.")
+  public func appendingPathExtension(_ ext: String) -> String? {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByDeletingLastPathComponent;
+
+  /// Returns a new string made by deleting the last path
+  /// component from the `String`, along with any final path
+  /// separator.
+  @available(*, unavailable, message: "Use deletingLastPathComponent on URL instead.")
+  public var deletingLastPathComponent: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByDeletingPathExtension;
+
+  /// Returns a new string made by deleting the extension (if
+  /// any, and only the last) from the `String`.
+  @available(*, unavailable, message: "Use deletingPathExtension on URL instead.")
+  public var deletingPathExtension: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByExpandingTildeInPath;
+
+  /// Returns a new string made by expanding the initial
+  /// component of the `String` to its full path value.
+  @available(*, unavailable, message: "Use expandingTildeInPath on NSString instead.")
+  public var expandingTildeInPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)
+  //     stringByFoldingWithOptions:(StringCompareOptions)options
+  //     locale:(Locale *)locale
+
+  @available(*, unavailable, renamed: "folding(options:locale:)")
+  public func folding(
+    _ options: String.CompareOptions = [], locale: Locale?
+  ) -> String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByResolvingSymlinksInPath;
+
+  /// Returns a new string made from the `String` by resolving
+  /// all symbolic links and standardizing path.
+  @available(*, unavailable, message: "Use resolvingSymlinksInPath on URL instead.")
+  public var resolvingSymlinksInPath: String {
+    fatalError("unavailable property")
+  }
+
+  // @property NSString* stringByStandardizingPath;
+
+  /// Returns a new string made by removing extraneous path
+  /// components from the `String`.
+  @available(*, unavailable, message: "Use standardizingPath on URL instead.")
+  public var standardizingPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSArray *)stringsByAppendingPaths:(NSArray *)paths
+
+  /// Returns an array of strings made by separately appending
+  /// to the `String` each string in a given array.
+  @available(*, unavailable, message: "Map over paths with appendingPathComponent instead.")
+  public func strings(byAppendingPaths paths: [String]) -> [String] {
+    fatalError("unavailable function can't be called")
+  }
+
+}
+
 // Pre-Swift-3 method names
 extension String {
-
   @available(*, unavailable, renamed: "localizedName(of:)")
   public static func localizedNameOfStringEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String {
     fatalError("unavailable function can't be called")
   }
@@ -1526,8 +1861,20 @@
     fatalError("unavailable function can't be called")
   }
 
+  // + (NSString *)pathWithComponents:(NSArray *)components
+
+  /// Returns a string built from the strings in a given array
+  /// by concatenating them with a path separator between each pair.
+  @available(*, unavailable, message: "Use fileURL(withPathComponents:) on URL instead.")
+  public static func path(withComponents components: [String]) -> String {
+    fatalError("unavailable function can't be called")
+  }
+}
+
+extension StringProtocol {
+
   @available(*, unavailable, renamed: "canBeConverted(to:)")
-  public func canBeConvertedToEncoding(_ encoding: Encoding) -> Bool {
+  public func canBeConvertedToEncoding(_ encoding: String.Encoding) -> Bool {
     fatalError("unavailable function can't be called")
   }
 
@@ -1538,7 +1885,7 @@
 
   @available(*, unavailable, renamed: "commonPrefix(with:options:)")
   public func commonPrefixWith(
-    _ aString: String, options: CompareOptions) -> String {
+    _ aString: String, options: String.CompareOptions) -> String {
     fatalError("unavailable function can't be called")
   }
 
@@ -1565,22 +1912,36 @@
   }
 
   @available(*, unavailable, renamed: "cString(usingEncoding:)")
-  public func cStringUsingEncoding(_ encoding: Encoding) -> [CChar]? {
+  public func cStringUsingEncoding(_ encoding: String.Encoding) -> [CChar]? {
     fatalError("unavailable function can't be called")
   }
 
   @available(*, unavailable, renamed: "data(usingEncoding:allowLossyConversion:)")
   public func dataUsingEncoding(
-    _ encoding: Encoding,
+    _ encoding: String.Encoding,
     allowLossyConversion: Bool = false
   ) -> Data? {
     fatalError("unavailable function can't be called")
   }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  @available(*, unavailable, renamed: "enumerateLinguisticTags(in:scheme:options:orthography:_:)")
+  public func enumerateLinguisticTagsIn(
+    _ range: Range<Index>,
+    scheme tagScheme: String,
+    options opts: NSLinguisticTagger.Options,
+    orthography: NSOrthography?,
+    _ body:
+      (String, Range<Index>, Range<Index>, inout Bool) -> Void
+  ) {
+    fatalError("unavailable function can't be called")
+  }
+#endif
+
   @available(*, unavailable, renamed: "enumerateSubstrings(in:options:_:)")
   public func enumerateSubstringsIn(
     _ range: Range<Index>,
-    options opts: EnumerationOptions = [],
+    options opts: String.EnumerationOptions = [],
     _ body: (
       _ substring: String?, _ substringRange: Range<Index>,
       _ enclosingRange: Range<Index>, inout Bool
@@ -1594,8 +1955,8 @@
     _ buffer: inout [UInt8],
     maxLength maxBufferCount: Int,
     usedLength usedBufferCount: UnsafeMutablePointer<Int>,
-    encoding: Encoding,
-    options: EncodingConversionOptions = [],
+    encoding: String.Encoding,
+    options: String.EncodingConversionOptions = [],
     range: Range<Index>,
     remainingRange leftover: UnsafeMutablePointer<Range<Index>>
   ) -> Bool {
@@ -1623,7 +1984,7 @@
   }
 
   @available(*, unavailable, renamed: "lengthOfBytes(using:)")
-  public func lengthOfBytesUsingEncoding(_ encoding: Encoding) -> Int {
+  public func lengthOfBytesUsingEncoding(_ encoding: String.Encoding) -> Int {
     fatalError("unavailable function can't be called")
   }
 
@@ -1632,6 +1993,19 @@
     fatalError("unavailable function can't be called")
   }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  @available(*, unavailable, renamed: "linguisticTags(in:scheme:options:orthography:tokenRanges:)")
+  public func linguisticTagsIn(
+    _ range: Range<Index>,
+    scheme tagScheme: String,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    tokenRanges: UnsafeMutablePointer<[Range<Index>]>? = nil
+  ) -> [String] {
+    fatalError("unavailable function can't be called")
+  }
+#endif
+
   @available(*, unavailable, renamed: "lowercased(with:)")
   public func lowercaseStringWith(_ locale: Locale?) -> String {
     fatalError("unavailable function can't be called")
@@ -1639,7 +2013,7 @@
 
   @available(*, unavailable, renamed: "maximumLengthOfBytes(using:)")
   public
-  func maximumLengthOfBytesUsingEncoding(_ encoding: Encoding) -> Int {
+  func maximumLengthOfBytesUsingEncoding(_ encoding: String.Encoding) -> Int {
     fatalError("unavailable function can't be called")
   }
 
@@ -1651,7 +2025,7 @@
   @available(*, unavailable, renamed: "rangeOfCharacter(from:options:range:)")
   public func rangeOfCharacterFrom(
     _ aSet: CharacterSet,
-    options mask: CompareOptions = [],
+    options mask: String.CompareOptions = [],
     range aRange: Range<Index>? = nil
   ) -> Range<Index>? {
     fatalError("unavailable function can't be called")
@@ -1673,7 +2047,7 @@
   @available(*, unavailable, renamed: "range(of:options:range:locale:)")
   public func rangeOf(
     _ aString: String,
-    options mask: CompareOptions = [],
+    options mask: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil,
     locale: Locale? = nil
   ) -> Range<Index>? {
@@ -1694,7 +2068,7 @@
 
   @available(*, unavailable, renamed: "addingPercentEscapes(using:)")
   public func addingPercentEscapesUsingEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String? {
     fatalError("unavailable function can't be called")
   }
@@ -1712,7 +2086,7 @@
   ) -> String {
     fatalError("unavailable function can't be called")
   }
-  
+
   @available(*, unavailable, renamed: "replacingCharacters(in:with:)")
   public func replacingCharactersIn(
     _ range: Range<Index>, withString replacement: String
@@ -1724,7 +2098,7 @@
   public func replacingOccurrencesOf(
     _ target: String,
     withString replacement: String,
-    options: CompareOptions = [],
+    options: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil
   ) -> String {
     fatalError("unavailable function can't be called")
@@ -1732,7 +2106,7 @@
 
   @available(*, unavailable, renamed: "replacingPercentEscapes(usingEncoding:)")
   public func replacingPercentEscapesUsingEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String? {
     fatalError("unavailable function can't be called")
   }
@@ -1770,7 +2144,7 @@
   @available(*, unavailable, renamed: "write(toFile:atomically:encoding:)")
   public func writeToFile(
     _ path: String, atomically useAuxiliaryFile:Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
     fatalError("unavailable function can't be called")
   }
@@ -1778,7 +2152,7 @@
   @available(*, unavailable, renamed: "write(to:atomically:encoding:)")
   public func writeToURL(
     _ url: URL, atomically useAuxiliaryFile: Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
     fatalError("unavailable function can't be called")
   }
diff --git a/Foundation/Operation.swift b/Foundation/Operation.swift
index 1c5529f..9c17ad1 100644
--- a/Foundation/Operation.swift
+++ b/Foundation/Operation.swift
@@ -9,13 +9,8 @@
 
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
 import Dispatch
-#if os(Linux) || os(Android)
+#endif
 import CoreFoundation
-private func pthread_main_np() -> Int32 {
-    return _CFIsMainThread() ? 1 : 0
-}
-#endif
-#endif
 
 open class Operation : NSObject {
     let lock = NSLock()
@@ -570,7 +565,7 @@
     open class var current: OperationQueue? {
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
         guard let specific = DispatchQueue.getSpecific(key: OperationQueue.OperationQueueKey) else {
-            if pthread_main_np() == 1 {
+            if _CFIsMainThread() {
                 return OperationQueue.main
             } else {
                 return nil
diff --git a/Foundation/Thread.swift b/Foundation/Thread.swift
index 3990db0..340ec7f 100644
--- a/Foundation/Thread.swift
+++ b/Foundation/Thread.swift
@@ -13,29 +13,23 @@
 #elseif os(Linux) || CYGWIN
 import Glibc
 #endif
-
 import CoreFoundation
 
-// for some reason having this take a generic causes a crash...
-private func _compiler_crash_fix(_ key: _CFThreadSpecificKey, _ value: AnyObject?) {
-    _CThreadSpecificSet(key, value)
-}
-
 internal class NSThreadSpecific<T: NSObject> {
     private var key = _CFThreadSpecificKeyCreate()
-    
+
     internal func get(_ generator: () -> T) -> T {
         if let specific = _CFThreadSpecificGet(key) {
             return specific as! T
         } else {
             let value = generator()
-            _compiler_crash_fix(key, value)
+            _CThreadSpecificSet(key, value)
             return value
         }
     }
-    
+
     internal func set(_ value: T) {
-        _compiler_crash_fix(key, value)
+        _CThreadSpecificSet(key, value)
     }
 }
 
@@ -57,18 +51,33 @@
 }
 
 open class Thread : NSObject {
-    
+
     static internal var _currentThread = NSThreadSpecific<Thread>()
     open class var current: Thread {
         return Thread._currentThread.get() {
-            return Thread(thread: pthread_self())
+            if Thread.isMainThread {
+                return mainThread
+            } else {
+                return Thread(thread: pthread_self())
+            }
         }
     }
-    
-    open class var isMainThread: Bool { NSUnimplemented() }
-    
+
+    open class var isMainThread: Bool {
+        return _CFIsMainThread()
+    }
+
     // !!! NSThread's mainThread property is incorrectly exported as "main", which conflicts with its "main" method.
-    open class var mainThread: Thread { NSUnimplemented() }
+    private static let _mainThread: Thread = {
+        var thread = Thread(thread: _CFMainPThread)
+        thread._status = .executing
+        return thread
+    }()
+
+    open class var mainThread: Thread {
+        return _mainThread
+    }
+
 
     /// Alternative API for detached thread creation
     /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative to creation via selector
@@ -77,11 +86,11 @@
         let t = Thread(block: block)
         t.start()
     }
-    
+
     open class func isMultiThreaded() -> Bool {
         return true
     }
-    
+
     open class func sleep(until date: Date) {
         let start_ut = CFGetSystemUptime()
         let start_at = CFAbsoluteTimeGetCurrent()
@@ -127,9 +136,10 @@
     }
 
     open class func exit() {
+        Thread.current._status = .finished
         pthread_exit(nil)
     }
-    
+
     internal var _main: () -> Void = {}
 #if os(OSX) || os(iOS) || CYGWIN
     private var _thread: pthread_t? = nil
@@ -145,12 +155,12 @@
     internal var _cancelled = false
     /// - Note: this differs from the Darwin implementation in that the keys must be Strings
     open var threadDictionary = [String : Any]()
-    
+
     internal init(thread: pthread_t) {
         // Note: even on Darwin this is a non-optional pthread_t; this is only used for valid threads, which are never null pointers.
         _thread = thread
     }
-    
+
     public override init() {
         let _ = withUnsafeMutablePointer(to: &_attr) { attr in
             pthread_attr_init(attr)
@@ -158,7 +168,7 @@
             pthread_attr_setdetachstate(attr, Int32(PTHREAD_CREATE_DETACHED))
         }
     }
-    
+
     public convenience init(block: @escaping () -> Swift.Void) {
         self.init()
         _main = block
@@ -185,11 +195,11 @@
         }
 #endif
     }
-    
+
     open func main() {
         _main()
     }
-    
+
     open var name: String? {
         didSet {
             if _thread == Thread.current._thread {
@@ -227,25 +237,52 @@
     open var isFinished: Bool {
         return _status == .finished
     }
-    
+
     open var isCancelled: Bool {
         return _cancelled
     }
-    
+
     open var isMainThread: Bool {
-        NSUnimplemented()
+        return self === Thread.mainThread
     }
-    
+
     open func cancel() {
         _cancelled = true
     }
 
-    open class var callStackReturnAddresses: [NSNumber] {
-        NSUnimplemented()
+
+    private class func backtraceAddresses<T>(_ body: (UnsafeMutablePointer<UnsafeMutableRawPointer?>, Int) -> [T]) -> [T] {
+        // Same as swift/stdlib/public/runtime/Errors.cpp backtrace
+        let maxSupportedStackDepth = 128;
+        let addrs = UnsafeMutablePointer<UnsafeMutableRawPointer?>.allocate(capacity: maxSupportedStackDepth)
+        defer { addrs.deallocate(capacity: maxSupportedStackDepth) }
+        let count = backtrace(addrs, Int32(maxSupportedStackDepth))
+        let addressCount = max(0, min(Int(count), maxSupportedStackDepth))
+        return body(addrs, addressCount)
     }
-    
+
+    open class var callStackReturnAddresses: [NSNumber] {
+        return backtraceAddresses({ (addrs, count) in
+            UnsafeBufferPointer(start: addrs, count: count).map {
+                NSNumber(value: UInt(bitPattern: $0))
+            }
+        })
+    }
+
     open class var callStackSymbols: [String] {
-        NSUnimplemented()
+        return backtraceAddresses({ (addrs, count) in
+            var symbols: [String] = []
+            if let bs = backtrace_symbols(addrs, Int32(count)) {
+                symbols = UnsafeBufferPointer(start: bs, count: count).map {
+                    guard let symbol = $0 else {
+                        return "<null>"
+                    }
+                    return String(cString: symbol)
+                }
+                free(bs)
+            }
+            return symbols
+        })
     }
 }
 
diff --git a/Foundation/URLSession/URLSession.swift b/Foundation/URLSession/URLSession.swift
index 9dbb84c..3a07673 100644
--- a/Foundation/URLSession/URLSession.swift
+++ b/Foundation/URLSession/URLSession.swift
@@ -171,12 +171,21 @@
 import CoreFoundation
 import Dispatch
 
+extension URLSession {
+    public enum DelayedRequestDisposition {
+        case cancel
+        case continueLoading
+        case useNewRequest
+    }
+}
 
+fileprivate let globalVarSyncQ = DispatchQueue(label: "org.swift.Foundation.URLSession.GlobalVarSyncQ")
 fileprivate var sessionCounter = Int32(0)
 fileprivate func nextSessionIdentifier() -> Int32 {
-    //TODO: find an alternative for OSAtomicIncrement32Barrier() on Linux
-    sessionCounter += 1
-    return sessionCounter
+    return globalVarSyncQ.sync {
+        sessionCounter += 1
+        return sessionCounter
+    }
 }
 public let NSURLSessionTransferSizeUnknown: Int64 = -1
 
diff --git a/Foundation/URLSession/URLSessionDelegate.swift b/Foundation/URLSession/URLSessionDelegate.swift
index ab9c077..3c65fb9 100644
--- a/Foundation/URLSession/URLSessionDelegate.swift
+++ b/Foundation/URLSession/URLSessionDelegate.swift
@@ -119,6 +119,8 @@
      * nil, which implies that no error occurred and this task is complete.
      */
      func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
+    
+     func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void)
 }
 
 extension URLSessionTaskDelegate {
@@ -137,6 +139,8 @@
     public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { }
     
     public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { }
+    
+    public func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void) { }
 }
 
 /*
@@ -194,6 +198,7 @@
      * message to receive the resource data.
      */
      func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void)
+    
 }
 
 extension URLSessionDataDelegate {
diff --git a/Foundation/URLSession/URLSessionTask.swift b/Foundation/URLSession/URLSessionTask.swift
index 1115ef5..6149f17 100644
--- a/Foundation/URLSession/URLSessionTask.swift
+++ b/Foundation/URLSession/URLSessionTask.swift
@@ -21,22 +21,23 @@
 import CoreFoundation
 import Dispatch
 
-
 /// A cancelable object that refers to the lifetime
 /// of processing a given request.
 open class URLSessionTask : NSObject, NSCopying {
+    
+    public var countOfBytesClientExpectsToReceive: Int64 { NSUnimplemented() }
+    public var countOfBytesClientExpectsToSend: Int64 { NSUnimplemented() }
+    public var earliestBeginDate: Date? { NSUnimplemented() }
+    
     /// How many times the task has been suspended, 0 indicating a running task.
     internal var suspendCount = 1
     internal var session: URLSessionProtocol! //change to nil when task completes
     internal let body: _Body
     fileprivate var _protocol: URLProtocol! = nil
+    private let syncQ = DispatchQueue(label: "org.swift.URLSessionTask.SyncQ")
     
     /// All operations must run on this queue.
     internal let workQueue: DispatchQueue 
-    /// Using dispatch semaphore to make public attributes thread safe.
-    /// A semaphore is a simpler option against the usage of concurrent queue
-    /// as the critical sections are very short.
-    fileprivate let semaphore = DispatchSemaphore(value: 1)    
     
     public override init() {
         // Darwin Foundation oddly allows calling this initializer, even though
@@ -62,7 +63,8 @@
     }
     internal init(session: URLSession, request: URLRequest, taskIdentifier: Int, body: _Body) {
         self.session = session
-        self.workQueue = session.workQueue
+        /* make sure we're actually having a serial queue as it's used for synchronization */
+        self.workQueue = DispatchQueue.init(label: "org.swift.URLSessionTask.WorkQueue", target: session.workQueue)
         self.taskIdentifier = taskIdentifier
         self.originalRequest = request
         self.body = body
@@ -108,31 +110,19 @@
     /// May differ from originalRequest due to http server redirection
     /*@NSCopying*/ open internal(set) var currentRequest: URLRequest? {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._currentRequest
+            return self.syncQ.sync { return self._currentRequest }
         }
         set {
-            semaphore.wait()
-            self._currentRequest = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._currentRequest = newValue }
         }
     }
     fileprivate var _currentRequest: URLRequest? = nil
     /*@NSCopying*/ open internal(set) var response: URLResponse? {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._response
+            return self.syncQ.sync { return self._response }
         }
         set {
-            semaphore.wait()
-            self._response = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._response = newValue }
         }
     }
     fileprivate var _response: URLResponse? = nil
@@ -145,16 +135,10 @@
     /// Number of body bytes already received
     open internal(set) var countOfBytesReceived: Int64 {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._countOfBytesReceived
+            return self.syncQ.sync { return self._countOfBytesReceived }
         }
         set {
-            semaphore.wait()
-            self._countOfBytesReceived = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._countOfBytesReceived = newValue }
         }
     }
     fileprivate var _countOfBytesReceived: Int64 = 0
@@ -162,16 +146,10 @@
     /// Number of body bytes already sent */
     open internal(set) var countOfBytesSent: Int64 {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._countOfBytesSent
+            return self.syncQ.sync { return self._countOfBytesSent }
         }
         set {
-            semaphore.wait()
-            self._countOfBytesSent = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._countOfBytesSent = newValue }
         }
     }
     
@@ -211,16 +189,10 @@
      */
     open var state: URLSessionTask.State {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._state
+            return self.syncQ.sync { self._state }
         }
         set {
-            semaphore.wait()
-            self._state = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._state = newValue }
         }
     }
     fileprivate var _state: URLSessionTask.State = .suspended
@@ -301,16 +273,10 @@
     /// URLSessionTask.highPriority, but use is not restricted to these.
     open var priority: Float {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._priority
+            return self.workQueue.sync { return self._priority }
         }
         set {
-            semaphore.wait()
-            self._priority = newValue
-            semaphore.signal()
+            self.workQueue.sync { self._priority = newValue }
         }
     }
     fileprivate var _priority: Float = URLSessionTask.defaultPriority
@@ -328,6 +294,12 @@
     }
 }
 
+extension URLSessionTask : ProgressReporting {
+    public var progress: Progress {
+        NSUnimplemented()
+    }
+}
+
 internal extension URLSessionTask {
     /// Updates the (public) state based on private / internal state.
     ///
@@ -555,7 +527,9 @@
             session.delegateQueue.addOperation {
                 delegate.urlSession(session, task: task, didCompleteWithError: nil)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .noDelegate:
             task.state = .completed
@@ -606,7 +580,9 @@
             session.delegateQueue.addOperation {
                 delegate.urlSession(session, task: task, didCompleteWithError: error as Error)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .noDelegate:
             task.state = .completed
@@ -615,7 +591,9 @@
             session.delegateQueue.addOperation {
                 completion(nil, nil, error)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .downloadCompletionHandler(let completion):
             session.delegateQueue.addOperation {
diff --git a/Foundation/Unit.swift b/Foundation/Unit.swift
index 92a9c6a..f43e5ff 100644
--- a/Foundation/Unit.swift
+++ b/Foundation/Unit.swift
@@ -79,6 +79,19 @@
     }
     
     public static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConverterLinear else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.coefficient == other.coefficient
+            && self.constant == other.constant
+    }
 }
 
 private class UnitConverterReciprocal : UnitConverter, NSSecureCoding {
@@ -115,6 +128,18 @@
     }
     
     fileprivate static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConverterReciprocal else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.reciprocal == other.reciprocal
+    }
 }
 
 /*
@@ -127,7 +152,7 @@
     open private(set) var symbol: String
     
     
-    public init(symbol: String) {
+    public required init(symbol: String) {
         self.symbol = symbol
     }
     
@@ -150,8 +175,20 @@
         }
         aCoder.encode(self.symbol._bridgeToObjectiveC(), forKey:"NS.symbol")
     }
-
+    
     public static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? Unit else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.symbol == other.symbol
+    }
 }
 
 open class Dimension : Unit {
@@ -159,8 +196,7 @@
     
     open private(set) var converter: UnitConverter
     
-    
-    public init(symbol: String, converter: UnitConverter) {
+    public required init(symbol: String, converter: UnitConverter) {
         self.converter = converter
         super.init(symbol: symbol)
     }
@@ -186,6 +222,11 @@
         super.init(symbol: symbol)
     }
     
+    public required init(symbol: String) {
+        let T = type(of: self)
+        fatalError("\(T) must be initialized with designated initializer \(T).init(symbol: String, converter: UnitConverter)")
+    }
+    
     open override func encode(with aCoder: NSCoder) {
         super.encode(with: aCoder)
         guard aCoder.allowsKeyedCoding else {
@@ -193,6 +234,18 @@
         }
         aCoder.encode(self.converter, forKey:"converter")
     }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? Dimension else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object) && self.converter == other.converter
+    }
 }
 
 open class UnitAcceleration : Dimension {
@@ -211,8 +264,8 @@
         static let gravity                  = 9.81
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var metersPerSecondSquared: UnitAcceleration {
@@ -231,9 +284,17 @@
         return UnitAcceleration.metersPerSecondSquared
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitAcceleration else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitAngle : Dimension {
@@ -260,11 +321,10 @@
         static let revolutions  = 360.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var degrees: UnitAngle {
         get {
             return UnitAngle(symbol: Symbol.degrees, coefficient: Coefficient.degrees)
@@ -305,9 +365,17 @@
         return UnitAngle.degrees
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitAngle else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitArea : Dimension {
@@ -350,11 +418,10 @@
         static let hectares             = 10000.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var squareMegameters: UnitArea {
         get {
             return UnitArea(symbol: Symbol.squareMegameters, coefficient: Coefficient.squareMegameters)
@@ -443,9 +510,17 @@
         return UnitArea.squareMeters
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitArea else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitConcentrationMass : Dimension {
@@ -466,11 +541,10 @@
         static let millimolesPerLiter       = 18.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var gramsPerLiter: UnitConcentrationMass {
         get {
             return UnitConcentrationMass(symbol: Symbol.gramsPerLiter, coefficient: Coefficient.gramsPerLiter)
@@ -491,9 +565,17 @@
         return UnitConcentrationMass.gramsPerLiter
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConcentrationMass else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitDispersion : Dimension {
@@ -510,11 +592,10 @@
         static let partsPerMillion  = 1.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var partsPerMillion: UnitDispersion {
         get {
             return UnitDispersion(symbol: Symbol.partsPerMillion, coefficient: Coefficient.partsPerMillion)
@@ -525,9 +606,17 @@
         return UnitDispersion.partsPerMillion
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitDispersion else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitDuration : Dimension {
@@ -548,8 +637,8 @@
         static let hours    = 3600.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var seconds: UnitDuration {
@@ -574,9 +663,17 @@
         return UnitDuration.seconds
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitDuration else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricCharge : Dimension {
@@ -602,11 +699,10 @@
         static let microampereHours = 0.0036
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var coulombs: UnitElectricCharge {
         get {
             return UnitElectricCharge(symbol: Symbol.coulombs, coefficient: Coefficient.coulombs)
@@ -647,9 +743,17 @@
         return UnitElectricCharge.coulombs
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricCharge else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricCurrent : Dimension {
@@ -657,6 +761,7 @@
     /*
      Base unit - amperes
      */
+    
     private struct Symbol {
         static let megaamperes  = "MA"
         static let kiloamperes  = "kA"
@@ -674,11 +779,10 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megaamperes: UnitElectricCurrent {
         get {
             return UnitElectricCurrent(symbol: Symbol.megaamperes, coefficient: Coefficient.megaamperes)
@@ -713,9 +817,17 @@
         return UnitElectricCurrent.amperes
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricCurrent else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricPotentialDifference : Dimension {
@@ -741,11 +853,10 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megavolts: UnitElectricPotentialDifference {
         get {
             return UnitElectricPotentialDifference(symbol: Symbol.megavolts, coefficient: Coefficient.megavolts)
@@ -780,9 +891,17 @@
         return UnitElectricPotentialDifference.volts
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricPotentialDifference else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricResistance : Dimension {
@@ -808,8 +927,8 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var megaohms: UnitElectricResistance {
@@ -846,9 +965,17 @@
         return UnitElectricResistance.ohms
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricResistance else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitEnergy : Dimension {
@@ -874,8 +1001,8 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var kilojoules: UnitEnergy {
@@ -912,9 +1039,17 @@
         return UnitEnergy.joules
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitEnergy else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitFrequency : Dimension {
@@ -945,11 +1080,10 @@
         static let nanohertz    = 1e-9
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var terahertz: UnitFrequency {
         get {
             return UnitFrequency(symbol: Symbol.terahertz, coefficient: Coefficient.terahertz)
@@ -1002,9 +1136,17 @@
         return UnitFrequency.hertz
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitFrequency else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitFuelEfficiency : Dimension {
@@ -1025,11 +1167,10 @@
         static let milesPerGallon           = 235.215
     }
     
-    private init(symbol: String, reciprocal: Double) {
-        super.init(symbol: symbol, converter: UnitConverterReciprocal(reciprocal: reciprocal))
+    private convenience init(symbol: String, reciprocal: Double) {
+        self.init(symbol: symbol, converter: UnitConverterReciprocal(reciprocal: reciprocal))
     }
     
-    
     open class var litersPer100Kilometers: UnitFuelEfficiency {
         get {
             return UnitFuelEfficiency(symbol: Symbol.litersPer100Kilometers, reciprocal: Coefficient.litersPer100Kilometers)
@@ -1052,9 +1193,17 @@
         return UnitFuelEfficiency.litersPer100Kilometers
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitFuelEfficiency else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitLength : Dimension {
@@ -1113,8 +1262,8 @@
         static let parsecs              = 3.086e+16
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var megameters: UnitLength {
@@ -1253,9 +1402,17 @@
         return UnitLength.meters
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitLength else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitIlluminance : Dimension {
@@ -1272,8 +1429,8 @@
         static let lux   = 1.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var lux: UnitIlluminance {
@@ -1286,9 +1443,17 @@
         return UnitIlluminance.lux
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitIlluminance else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitMass : Dimension {
@@ -1335,8 +1500,8 @@
         static let slugs        = 14.5939
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var kilograms: UnitMass {
@@ -1439,9 +1604,17 @@
         return UnitMass.kilograms
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitMass else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitPower : Dimension {
@@ -1478,8 +1651,8 @@
         static let horsepower = 745.7
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var terawatts: UnitPower {
@@ -1552,9 +1725,17 @@
         return UnitPower.watts
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitPower else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitPressure : Dimension {
@@ -1589,11 +1770,10 @@
         static let poundsForcePerSquareInch = 6894.76
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var newtonsPerMetersSquared: UnitPressure {
         get {
             return UnitPressure(symbol: Symbol.newtonsPerMetersSquared, coefficient: Coefficient.newtonsPerMetersSquared)
@@ -1658,9 +1838,17 @@
         return UnitPressure.newtonsPerMetersSquared
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitPressure else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitSpeed : Dimension {
@@ -1683,11 +1871,10 @@
         static let knots                = 0.514444
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var metersPerSecond: UnitSpeed {
         get {
             return UnitSpeed(symbol: Symbol.metersPerSecond, coefficient: Coefficient.metersPerSecond)
@@ -1716,9 +1903,17 @@
         return UnitSpeed.metersPerSecond
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitSpeed else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitTemperature : Dimension {
@@ -1745,8 +1940,8 @@
         static let fahrenheit = 255.37222222222427
     }
     
-    private init(symbol: String, coefficient: Double, constant: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant))
+    private convenience init(symbol: String, coefficient: Double, constant: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant))
     }
     
     open class var kelvin: UnitTemperature {
@@ -1771,9 +1966,17 @@
         return UnitTemperature.kelvin
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitTemperature else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitVolume : Dimension {
@@ -1850,11 +2053,10 @@
         static let metricCups           = 0.25
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megaliters: UnitVolume {
         get {
             return UnitVolume(symbol: Symbol.megaliters, coefficient: Coefficient.megaliters)
@@ -2045,6 +2247,15 @@
         return UnitVolume.liters
     }
     
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitVolume else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
diff --git a/TestFoundation/HTTPServer.swift b/TestFoundation/HTTPServer.swift
index fccbad1..f52b771 100644
--- a/TestFoundation/HTTPServer.swift
+++ b/TestFoundation/HTTPServer.swift
@@ -26,6 +26,8 @@
 #endif
 
 public let globalDispatchQueue = DispatchQueue.global()
+public let dispatchQueueMake: (String) -> DispatchQueue = { DispatchQueue.init(label: $0) }
+public let dispatchGroupMake: () -> DispatchGroup = DispatchGroup.init
 
 struct _HTTPUtils {
     static let CRLF = "\r\n"
diff --git a/TestFoundation/TestCodable.swift b/TestFoundation/TestCodable.swift
index c43becf..f1fb7d6 100644
--- a/TestFoundation/TestCodable.swift
+++ b/TestFoundation/TestCodable.swift
@@ -399,6 +399,13 @@
         let components = calendar.dateComponents(dateComponents, from: Date(timeIntervalSince1970: 1501283776))
         expectRoundTripEqualityThroughJSON(for: components)
     }
+
+    // MARK: - Measurement
+    func test_Measurement_JSON() {
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitAcceleration.metersPerSecondSquared))
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitMass.kilograms))
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitLength.miles))
+    }
 }
 
 extension TestCodable {
@@ -420,6 +427,7 @@
             ("test_TimeZone_JSON", test_TimeZone_JSON),
             ("test_Calendar_JSON", test_Calendar_JSON),
             ("test_DateComponents_JSON", test_DateComponents_JSON),
+            ("test_Measurement_JSON", test_Measurement_JSON),
         ]
     }
 }
diff --git a/TestFoundation/TestHTTPCookieStorage.swift b/TestFoundation/TestHTTPCookieStorage.swift
index bea3391..472e34a 100644
--- a/TestFoundation/TestHTTPCookieStorage.swift
+++ b/TestFoundation/TestHTTPCookieStorage.swift
@@ -230,7 +230,7 @@
         let bundlePath = Bundle.main.bundlePath
         var bundleName = "/" + bundlePath.components(separatedBy: "/").last!
         if let range = bundleName.range(of: ".", options: String.CompareOptions.backwards, range: nil, locale: nil) {
-            bundleName = bundleName.substring(to: range.lowerBound)
+            bundleName = String(bundleName[..<range.lowerBound])
         }
         if let xdg_data_home = getenv("XDG_DATA_HOME") {
             destPath = String(utf8String: xdg_data_home)! + bundleName + "/.cookies.shared"
@@ -251,7 +251,7 @@
         let exeName = "/xdgTestHelper/xdgTestHelper"
         #endif
 
-        task.launchPath = bundlePath.substring(to: pathIndex!) + exeName
+        task.launchPath = bundlePath[..<pathIndex!] + exeName
         var environment = ProcessInfo.processInfo.environment
         let testPath = NSHomeDirectory() + "/TestXDG"
         environment["XDG_DATA_HOME"] = testPath
diff --git a/TestFoundation/TestJSONEncoder.swift b/TestFoundation/TestJSONEncoder.swift
index 8631442..6444296 100644
--- a/TestFoundation/TestJSONEncoder.swift
+++ b/TestFoundation/TestJSONEncoder.swift
@@ -401,6 +401,68 @@
         test_codingOf(value: URL(string: "https://swift.org")!, toAndFrom: "\"https://swift.org\"")
     }
 
+
+    // UInt and Int
+    func test_codingOfUIntMinMax() {
+
+        let encoder = JSONEncoder()
+
+        struct MyValue: Codable {
+            let intMin:Int = Int.min
+            let intMax:Int = Int.max
+            let uintMin:UInt = UInt.min
+            let uintMax:UInt = UInt.max
+        }
+
+        let myValue = MyValue()
+        let myDictI: [String:Any] = ["intMin": myValue.intMin, "intMax": myValue.intMax]
+        let myDictU: [String:Any] = ["uintMin": myValue.uintMin, "uintMax": myValue.uintMax]
+        let myDict1: [String:Any] = ["intMin": myValue.intMin]
+        let myDict2: [String:Any] = ["intMax": myValue.intMax]
+        let myDict3: [String:Any] = ["uintMin": myValue.uintMin]
+        let myDict4: [String:Any] = ["uintMax": myValue.uintMax]
+
+        func compareJSON(_ s1: String, _ s2: String) {
+            let ss1 = s1.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
+            let ss2 = s2.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
+            XCTAssertEqual(ss1, ss2)
+        }
+
+        do {
+            let result = try encoder.encode(myValue)
+            let r = String(data: result, encoding: .utf8) ?? "nil"
+            compareJSON(r, "{\"uintMin\":0,\"uintMax\":18446744073709551615,\"intMin\":-9223372036854775808,\"intMax\":9223372036854775807}")
+
+            let resultI = try JSONSerialization.data(withJSONObject: myDictI)
+            let rI = String(data: resultI, encoding: .utf8) ?? "nil"
+            compareJSON(rI, "{\"intMin\":-9223372036854775808,\"intMax\":9223372036854775807}")
+
+            let resultU = try JSONSerialization.data(withJSONObject: myDictU)
+            let rU = String(data: resultU, encoding: .utf8) ?? "nil"
+            compareJSON(rU, "{\"uintMax\":18446744073709551615,\"uintMin\":0}")
+
+            let result1 = try JSONSerialization.data(withJSONObject: myDict1)
+            let r1 = String(data: result1, encoding: .utf8) ?? "nil"
+            XCTAssertEqual(r1, "{\"intMin\":-9223372036854775808}")
+
+            let result2 = try JSONSerialization.data(withJSONObject: myDict2)
+            let r2 = String(data: result2, encoding: .utf8) ?? "nil"
+            XCTAssertEqual(r2, "{\"intMax\":9223372036854775807}")
+
+            let result3 = try JSONSerialization.data(withJSONObject: myDict3)
+            let r3 = String(data: result3, encoding: .utf8) ?? "nil"
+            XCTAssertEqual(r3, "{\"uintMin\":0}")
+
+            let result4 = try JSONSerialization.data(withJSONObject: myDict4)
+            let r4 = String(data: result4, encoding: .utf8) ?? "nil"
+            XCTAssertEqual(r4, "{\"uintMax\":18446744073709551615}")
+        } catch {
+            XCTFail(String(describing: error))
+        }
+    }
+
+
+
     // MARK: - Helper Functions
     private var _jsonEmptyDictionary: Data {
         return "{}".data(using: .utf8)!
@@ -986,6 +1048,7 @@
             ("test_codingOfUInt64", test_codingOfUInt64),
             ("test_codingOfInt", test_codingOfInt),
             ("test_codingOfUInt", test_codingOfUInt),
+            ("test_codingOfUIntMinMax", test_codingOfUIntMinMax),
             ("test_codingOfFloat", test_codingOfFloat),
             ("test_codingOfDouble", test_codingOfDouble),
             ("test_codingOfString", test_codingOfString),
diff --git a/TestFoundation/TestNSData.swift b/TestFoundation/TestNSData.swift
index 020b2c1..df0cd2e 100644
--- a/TestFoundation/TestNSData.swift
+++ b/TestFoundation/TestNSData.swift
@@ -37,6 +37,8 @@
             ("test_base64Data_medium", test_base64Data_medium),
             ("test_base64Data_small", test_base64Data_small),
             ("test_openingNonExistentFile", test_openingNonExistentFile),
+            ("test_contentsOfFile", test_contentsOfFile),
+            ("test_contentsOfZeroFile", test_contentsOfZeroFile),
             ("test_basicReadWrite", test_basicReadWrite),
             ("test_bufferSizeCalculation", test_bufferSizeCalculation),
             // ("test_dataHash", test_dataHash),   Disabled due to lack of brdiging in swift runtime -- infinite loops
@@ -908,6 +910,47 @@
         XCTAssertTrue(didCatchError)
     }
 
+    func test_contentsOfFile() {
+        let testDir = testBundle().resourcePath
+        let filename = testDir!.appending("/NSStringTestData.txt")
+
+        let contents = NSData(contentsOfFile: filename)
+        XCTAssertNotNil(contents)
+        if let contents = contents {
+            let ptr =  UnsafeMutableRawPointer(mutating: contents.bytes)
+            let str = String(bytesNoCopy: ptr, length: contents.length,
+                         encoding: .ascii, freeWhenDone: false)
+            XCTAssertEqual(str, "swift-corelibs-foundation")
+        }
+    }
+
+    func test_contentsOfZeroFile() {
+#if os(Linux)
+        guard FileManager.default.fileExists(atPath: "/proc/self") else {
+            return
+        }
+        let contents = NSData(contentsOfFile: "/proc/self/cmdline")
+        XCTAssertNotNil(contents)
+        if let contents = contents {
+            XCTAssertTrue(contents.length > 0)
+            let ptr = UnsafeMutableRawPointer(mutating: contents.bytes)
+            let str = String(bytesNoCopy: ptr, length: contents.length,
+                             encoding: .ascii, freeWhenDone: false)
+            XCTAssertNotNil(str)
+            if let str = str {
+                XCTAssertTrue(str.hasSuffix("TestFoundation"))
+            }
+        }
+
+        do {
+            let maps = try String(contentsOfFile: "/proc/self/maps", encoding: .utf8)
+            XCTAssertTrue(maps.count > 0)
+        } catch {
+            XCTFail("Cannot read /proc/self/maps: \(String(describing: error))")
+        }
+#endif
+    }
+
     func test_basicReadWrite() {
         let url = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("testfile")
         let count = 1 << 24
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index d3ddde8..9d7fe2b 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -43,6 +43,7 @@
             ("test_description", test_description ),
             ("test_descriptionWithLocale", test_descriptionWithLocale ),
             ("test_objCType", test_objCType ),
+            ("test_stringValue", test_stringValue),
         ]
     }
     
@@ -1019,4 +1020,71 @@
         XCTAssertEqual("f" /* 0x66 */, objCType(NSNumber(value: Float.greatestFiniteMagnitude)))
         XCTAssertEqual("d" /* 0x64 */, objCType(NSNumber(value: Double.greatestFiniteMagnitude)))
     }
+
+    func test_stringValue() {
+
+        if UInt.max == UInt32.max {
+            XCTAssertEqual(NSNumber(value: UInt.min).stringValue, "0")
+            XCTAssertEqual(NSNumber(value: UInt.min + 1).stringValue, "1")
+            XCTAssertEqual(NSNumber(value: UInt.max).stringValue, "4294967295")
+            XCTAssertEqual(NSNumber(value: UInt.max - 1).stringValue, "4294967294")
+        } else if UInt.max == UInt64.max {
+            XCTAssertEqual(NSNumber(value: UInt.min).stringValue, "0")
+            XCTAssertEqual(NSNumber(value: UInt.min + 1).stringValue, "1")
+            XCTAssertEqual(NSNumber(value: UInt.max).stringValue, "18446744073709551615")
+            XCTAssertEqual(NSNumber(value: UInt.max - 1).stringValue, "18446744073709551614")
+        }
+
+        XCTAssertEqual(NSNumber(value: UInt8.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt8.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt8.max).stringValue, "255")
+        XCTAssertEqual(NSNumber(value: UInt8.max - 1).stringValue, "254")
+
+        XCTAssertEqual(NSNumber(value: UInt16.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt16.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt16.max).stringValue, "65535")
+        XCTAssertEqual(NSNumber(value: UInt16.max - 1).stringValue, "65534")
+
+        XCTAssertEqual(NSNumber(value: UInt32.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt32.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt32.max).stringValue, "4294967295")
+        XCTAssertEqual(NSNumber(value: UInt32.max - 1).stringValue, "4294967294")
+
+        XCTAssertEqual(NSNumber(value: UInt64.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt64.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt64.max).stringValue, "18446744073709551615")
+        XCTAssertEqual(NSNumber(value: UInt64.max - 1).stringValue, "18446744073709551614")
+
+        if Int.max == Int32.max {
+            XCTAssertEqual(NSNumber(value: Int.min).stringValue, "-2147483648")
+            XCTAssertEqual(NSNumber(value: Int.min + 1).stringValue, "-2147483647")
+            XCTAssertEqual(NSNumber(value: Int.max).stringValue, "2147483647")
+            XCTAssertEqual(NSNumber(value: Int.max - 1).stringValue, "2147483646")
+        } else if Int.max == Int64.max {
+            XCTAssertEqual(NSNumber(value: Int.min).stringValue, "-9223372036854775808")
+            XCTAssertEqual(NSNumber(value: Int.min + 1).stringValue, "-9223372036854775807")
+            XCTAssertEqual(NSNumber(value: Int.max).stringValue, "9223372036854775807")
+            XCTAssertEqual(NSNumber(value: Int.max - 1).stringValue, "9223372036854775806")
+        }
+
+        XCTAssertEqual(NSNumber(value: Int8.min).stringValue, "-128")
+        XCTAssertEqual(NSNumber(value: Int8.min + 1).stringValue, "-127")
+        XCTAssertEqual(NSNumber(value: Int8.max).stringValue, "127")
+        XCTAssertEqual(NSNumber(value: Int8.max - 1).stringValue, "126")
+
+        XCTAssertEqual(NSNumber(value: Int16.min).stringValue, "-32768")
+        XCTAssertEqual(NSNumber(value: Int16.min + 1).stringValue, "-32767")
+        XCTAssertEqual(NSNumber(value: Int16.max).stringValue, "32767")
+        XCTAssertEqual(NSNumber(value: Int16.max - 1).stringValue, "32766")
+
+        XCTAssertEqual(NSNumber(value: Int32.min).stringValue, "-2147483648")
+        XCTAssertEqual(NSNumber(value: Int32.min + 1).stringValue, "-2147483647")
+        XCTAssertEqual(NSNumber(value: Int32.max).stringValue, "2147483647")
+        XCTAssertEqual(NSNumber(value: Int32.max - 1).stringValue, "2147483646")
+
+        XCTAssertEqual(NSNumber(value: Int64.min).stringValue, "-9223372036854775808")
+        XCTAssertEqual(NSNumber(value: Int64.min + 1).stringValue, "-9223372036854775807")
+        XCTAssertEqual(NSNumber(value: Int64.max).stringValue, "9223372036854775807")
+        XCTAssertEqual(NSNumber(value: Int64.max - 1).stringValue, "9223372036854775806")
+    }
 }
diff --git a/TestFoundation/TestOperationQueue.swift b/TestFoundation/TestOperationQueue.swift
index f60f17b..02f95c4 100644
--- a/TestFoundation/TestOperationQueue.swift
+++ b/TestFoundation/TestOperationQueue.swift
@@ -175,12 +175,17 @@
 
     override internal(set) var isExecuting: Bool {
         get {
-            return _executing
+            lock.lock()
+            let wasExecuting = _executing
+            lock.unlock()
+            return wasExecuting
         }
         set {
-            if _executing != newValue {
+            if isExecuting != newValue {
                 willChangeValue(forKey: "isExecuting")
+                lock.lock()
                 _executing = newValue
+                lock.unlock()
                 didChangeValue(forKey: "isExecuting")
             }
         }
@@ -188,12 +193,17 @@
 
     override internal(set) var isFinished: Bool {
         get {
-            return _finished
+            lock.lock()
+            let wasFinished = _finished
+            lock.unlock()
+            return wasFinished
         }
         set {
-            if _finished != newValue {
+            if isFinished != newValue {
                 willChangeValue(forKey: "isFinished")
+                lock.lock()
                 _finished = newValue
+                lock.unlock()
                 didChangeValue(forKey: "isFinished")
             }
         }
@@ -213,10 +223,8 @@
 
         queue.async {
             sleep(1)
-            self.lock.lock()
             self.isExecuting = false
             self.isFinished = true
-            self.lock.unlock()
         }
     }
 
diff --git a/TestFoundation/TestProcess.swift b/TestFoundation/TestProcess.swift
index 163dc31..922c607 100644
--- a/TestFoundation/TestProcess.swift
+++ b/TestFoundation/TestProcess.swift
@@ -334,7 +334,7 @@
         guard let range = line.range(of: "=") else {
             throw Error.InvalidEnvironmentVariable(line)
         }
-        result[line.substring(to: range.lowerBound)] = line.substring(from: range.upperBound)
+        result[String(line[..<range.lowerBound])] = String(line[range.upperBound...])
     }
     return result
 }
diff --git a/TestFoundation/TestThread.swift b/TestFoundation/TestThread.swift
index 5630059..28478a4 100644
--- a/TestFoundation/TestThread.swift
+++ b/TestFoundation/TestThread.swift
@@ -24,6 +24,9 @@
             ("test_currentThread", test_currentThread ),
             ("test_threadStart", test_threadStart),
             ("test_threadName", test_threadName),
+            ("test_mainThread", test_mainThread),
+            ("test_callStackSymbols", test_callStackSymbols),
+            ("test_callStackReurnAddresses", test_callStackReturnAddresses),
         ]
     }
 
@@ -33,25 +36,22 @@
         XCTAssertNotNil(thread1)
         XCTAssertNotNil(thread2)
         XCTAssertEqual(thread1, thread2)
+        XCTAssertEqual(thread1, Thread.mainThread)
     }
     
     func test_threadStart() {
-        var started = false
         let condition = NSCondition()
         let thread = Thread() {
             condition.lock()
-            started = true
             condition.broadcast()
             condition.unlock()
         }
         thread.start()
         
         condition.lock()
-        if !started {
-            condition.wait()
-        }
+        let ok = condition.wait(until: Date(timeIntervalSinceNow: 10))
         condition.unlock()
-        XCTAssertTrue(started)
+        XCTAssertTrue(ok, "NSCondition wait timed out")
     }
     
     func test_threadName() {
@@ -84,4 +84,41 @@
         XCTAssertEqual(thread3.name, "Thread3")
         XCTAssertNotEqual(thread3.name, getPThreadName())
     }
+
+    func test_mainThread() {
+        XCTAssertTrue(Thread.isMainThread)
+        let t = Thread.mainThread
+        XCTAssertTrue(t.isMainThread)
+        let c = Thread.current
+        XCTAssertTrue(c.isMainThread)
+        XCTAssertTrue(c.isExecuting)
+        XCTAssertTrue(c.isEqual(t))
+
+        let condition = NSCondition()
+        let thread = Thread() {
+            condition.lock()
+            XCTAssertFalse(Thread.isMainThread)
+            XCTAssertFalse(Thread.mainThread == Thread.current)
+            condition.broadcast()
+            condition.unlock()
+        }
+        thread.start()
+
+        condition.lock()
+        let ok = condition.wait(until: Date(timeIntervalSinceNow: 10))
+        condition.unlock()
+        XCTAssertTrue(ok, "NSCondition wait timed out")
+    }
+
+    func test_callStackSymbols() {
+        let symbols = Thread.callStackSymbols
+        XCTAssertTrue(symbols.count > 0)
+        XCTAssertTrue(symbols.count <= 128)
+    }
+
+    func test_callStackReturnAddresses() {
+        let addresses = Thread.callStackReturnAddresses
+        XCTAssertTrue(addresses.count > 0)
+        XCTAssertTrue(addresses.count <= 128)
+    }
 }
diff --git a/TestFoundation/TestURLSession.swift b/TestFoundation/TestURLSession.swift
index cf44ab6..c941f1c 100644
--- a/TestFoundation/TestURLSession.swift
+++ b/TestFoundation/TestURLSession.swift
@@ -36,13 +36,14 @@
             ("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
             ("test_timeoutInterval", test_timeoutInterval),
             ("test_httpRedirection", test_httpRedirection),
-            ("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
+            //("test_httpRedirectionTimeout", test_httpRedirectionTimeout), /* temporarily disabled (https://bugs.swift.org/browse/SR-5751) */
             ("test_http0_9SimpleResponses", test_http0_9SimpleResponses),
             ("test_outOfRangeButCorrectlyFormattedHTTPCode", test_outOfRangeButCorrectlyFormattedHTTPCode),
             ("test_missingContentLengthButStillABody", test_missingContentLengthButStillABody),
             ("test_illegalHTTPServerResponses", test_illegalHTTPServerResponses),
             ("test_dataTaskWithSharedDelegate", test_dataTaskWithSharedDelegate),
             ("test_simpleUploadWithDelegate", test_simpleUploadWithDelegate),
+            ("test_concurrentRequests", test_concurrentRequests),
         ]
     }
     
@@ -312,6 +313,8 @@
         waitForExpectations(timeout: 12)
     }
 
+    /*
+     // temporarily disabled (https://bugs.swift.org/browse/SR-5751)
     func test_httpRedirectionTimeout() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
         var req = URLRequest(url: URL(string: urlString)!)
@@ -324,11 +327,14 @@
             if let e = error as? URLError {
                 XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
                 return
+            } else {
+                XCTFail("test unexpectedly succeeded (response=\(response.debugDescription))")
             }
         }
         task.resume()
         waitForExpectations(timeout: 12)
     }
+    */
 
     func test_http0_9SimpleResponses() {
         for brokenCity in ["Pompeii", "Sodom"] {
@@ -459,6 +465,34 @@
         task.resume()
         waitForExpectations(timeout: 20)
     }
+
+    func test_concurrentRequests() {
+        let syncQ = dispatchQueueMake("test_dataTaskWithURL.syncQ")
+        var dataTasks: [DataTask] = []
+        let g = dispatchGroupMake()
+        for f in 0..<640 {
+            g.enter()
+            let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
+            let expectation = self.expectation(description: "GET \(urlString) [\(f)]: with a delegate")
+            globalDispatchQueue.async {
+                let url = URL(string: urlString)!
+                let d = DataTask(with: expectation)
+                d.run(with: url)
+                syncQ.async {
+                    dataTasks.append(d)
+                    g.leave()
+                }
+            }
+        }
+        waitForExpectations(timeout: 12)
+        g.wait()
+        for d in syncQ.sync(execute: {dataTasks}) {
+            if !d.error {
+                XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
+            }
+        }
+    }
+
 }
 
 class SharedDelegate: NSObject {
@@ -488,19 +522,73 @@
 }
 
 class DataTask : NSObject {
+    let syncQ = dispatchQueueMake("org.swift.TestFoundation.TestURLSession.DataTask.syncQ")
     let dataTaskExpectation: XCTestExpectation!
-    var capital = "unknown"
-    var session: URLSession! = nil
-    var task: URLSessionDataTask! = nil
-    var cancelExpectation: XCTestExpectation?
-    var responseReceivedExpectation: XCTestExpectation?
-    var protocols: [AnyClass]?
+    let protocols: [AnyClass]?
+
+    /* all the following var _XYZ need to be synchronized on syncQ.
+       We can't just assert that we're on main thread here as we're modified in the URLSessionDataDelegate extension
+       for DataTask
+     */
+    var _capital = "unknown"
+    var capital: String {
+        get {
+            return self.syncQ.sync { self._capital }
+        }
+        set {
+            self.syncQ.sync { self._capital = newValue }
+        }
+    }
+    var _session: URLSession! = nil
+    var session: URLSession! {
+        get {
+            return self.syncQ.sync { self._session }
+        }
+        set {
+            self.syncQ.sync { self._session = newValue }
+        }
+    }
+    var _task: URLSessionDataTask! = nil
+    var task: URLSessionDataTask! {
+        get {
+            return self.syncQ.sync { self._task }
+        }
+        set {
+            self.syncQ.sync { self._task = newValue }
+        }
+    }
+    var _cancelExpectation: XCTestExpectation?
+    var cancelExpectation: XCTestExpectation? {
+        get {
+            return self.syncQ.sync { self._cancelExpectation }
+        }
+        set {
+            self.syncQ.sync { self._cancelExpectation = newValue }
+        }
+    }
+    var _responseReceivedExpectation: XCTestExpectation?
+    var responseReceivedExpectation: XCTestExpectation? {
+        get {
+            return self.syncQ.sync { self._responseReceivedExpectation }
+        }
+        set {
+            self.syncQ.sync { self._responseReceivedExpectation = newValue }
+        }
+    }
     
-    public var error = false
+    private var _error = false
+    public var error: Bool {
+        get {
+            return self.syncQ.sync { self._error }
+        }
+        set {
+            self.syncQ.sync { self._error = newValue }
+        }
+    }
     
     init(with expectation: XCTestExpectation, protocolClasses: [AnyClass]? = nil) {
         dataTaskExpectation = expectation
-	protocols = protocolClasses
+        protocols = protocolClasses
     }
     
     func run(with request: URLRequest) {
diff --git a/TestFoundation/TestUnit.swift b/TestFoundation/TestUnit.swift
new file mode 100644
index 0000000..c934965
--- /dev/null
+++ b/TestFoundation/TestUnit.swift
@@ -0,0 +1,103 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+    import Foundation
+    import XCTest
+#else
+    import SwiftFoundation
+    import SwiftXCTest
+#endif
+
+class TestUnit: XCTestCase {
+
+    static var allTests: [(String, (TestUnit) -> () throws -> Void)] {
+        return [
+            ("test_equality", test_equality),
+        ]
+    }
+
+    func test_equality() {
+        let s1 = "a"
+        let s2 = "ab"
+
+        let u1 = Unit(symbol: s1)
+        let u2 = Unit(symbol: s1)
+        let u3 = Unit(symbol: s2)
+
+        XCTAssertEqual(u1, u2)
+        XCTAssertEqual(u2, u1)
+        XCTAssertNotEqual(u1, u3)
+        XCTAssertNotEqual(u3, u1)
+
+        let uc1 = UnitConverterLinear(coefficient: 1, constant: 2)
+        let uc2 = UnitConverterLinear(coefficient: 1, constant: 3)
+
+        let d1 = Dimension(symbol: s1, converter: uc1)
+        let d2 = Dimension(symbol: s1, converter: uc1)
+        let d3 = Dimension(symbol: s2, converter: uc1)
+        let d4 = Dimension(symbol: s1, converter: uc2)
+
+        XCTAssertEqual(d1, d2)
+        XCTAssertEqual(d2, d1)
+        XCTAssertNotEqual(d1, d3)
+        XCTAssertNotEqual(d3, d1)
+        XCTAssertNotEqual(d1, d4)
+        XCTAssertNotEqual(d4, d1)
+
+        XCTAssertEqual(u1, d1)
+        XCTAssertNotEqual(d1, u1)
+
+        func testEquality<T: Dimension>(ofDimensionSubclass: T.Type) {
+            let u0 = Unit(symbol: s1)
+            let d1 = Dimension(symbol: s1, converter: uc1)
+
+            let u1 = T(symbol: s1, converter: uc1)
+            let u2 = T(symbol: s1, converter: uc1)
+            let u3 = T(symbol: s1, converter: uc2)
+            let u4 = T(symbol: s2, converter: uc1)
+
+            XCTAssertEqual(u1, u2)
+            XCTAssertEqual(u2, u1)
+            XCTAssertNotEqual(u1, u3)
+            XCTAssertNotEqual(u3, u1)
+            XCTAssertNotEqual(u1, u4)
+            XCTAssertNotEqual(u4, u1)
+
+            XCTAssertEqual(u0, u1)
+            XCTAssertNotEqual(u1, u0)
+
+            XCTAssertEqual(d1, u1)
+            XCTAssertNotEqual(u1, d1)
+        }
+
+        testEquality(ofDimensionSubclass: UnitAcceleration.self)
+        testEquality(ofDimensionSubclass: UnitAngle.self)
+        testEquality(ofDimensionSubclass: UnitArea.self)
+        testEquality(ofDimensionSubclass: UnitConcentrationMass.self)
+        testEquality(ofDimensionSubclass: UnitDispersion.self)
+        testEquality(ofDimensionSubclass: UnitDuration.self)
+        testEquality(ofDimensionSubclass: UnitElectricCharge.self)
+        testEquality(ofDimensionSubclass: UnitElectricCurrent.self)
+        testEquality(ofDimensionSubclass: UnitElectricPotentialDifference.self)
+        testEquality(ofDimensionSubclass: UnitElectricResistance.self)
+        testEquality(ofDimensionSubclass: UnitEnergy.self)
+        testEquality(ofDimensionSubclass: UnitFrequency.self)
+        testEquality(ofDimensionSubclass: UnitFuelEfficiency.self)
+        testEquality(ofDimensionSubclass: UnitIlluminance.self)
+        testEquality(ofDimensionSubclass: UnitLength.self)
+        testEquality(ofDimensionSubclass: UnitMass.self)
+        testEquality(ofDimensionSubclass: UnitPower.self)
+        testEquality(ofDimensionSubclass: UnitPressure.self)
+        testEquality(ofDimensionSubclass: UnitSpeed.self)
+        testEquality(ofDimensionSubclass: UnitTemperature.self)
+        testEquality(ofDimensionSubclass: UnitVolume.self)
+    }
+
+}
diff --git a/TestFoundation/TestUnitConverter.swift b/TestFoundation/TestUnitConverter.swift
index e03e6bb..ed1d374 100644
--- a/TestFoundation/TestUnitConverter.swift
+++ b/TestFoundation/TestUnitConverter.swift
@@ -24,6 +24,7 @@
             ("test_baseUnit", test_linearity),
             ("test_linearity", test_linearity),
             ("test_bijectivity", test_bijectivity),
+            ("test_equality", test_equality),
         ]
     }
     
@@ -267,5 +268,22 @@
         XCTAssertEqual(testIdentity(UnitVolume.imperialGallons), 1, accuracy: delta)
         XCTAssertEqual(testIdentity(UnitVolume.metricCups), 1, accuracy: delta)
     }
+
+    func test_equality() {
+        let u1 = UnitConverterLinear(coefficient: 1, constant: 2)
+        let u2 = UnitConverterLinear(coefficient: 1, constant: 2)
+        XCTAssertEqual(u1, u2)
+        XCTAssertEqual(u2, u1)
+
+        let u3 = UnitConverterLinear(coefficient: 1, constant: 3)
+        XCTAssertNotEqual(u1, u3)
+        XCTAssertNotEqual(u3, u1)
+
+        let u4 = UnitConverterLinear(coefficient: 2, constant: 2)
+        XCTAssertNotEqual(u1, u4)
+        XCTAssertNotEqual(u4, u1)
+
+        // Cannot test UnitConverterReciprocal due to no support for @testable import.
+    }
     
 }
diff --git a/TestFoundation/TestXMLParser.swift b/TestFoundation/TestXMLParser.swift
index 84e5782..b08f0b3 100644
--- a/TestFoundation/TestXMLParser.swift
+++ b/TestFoundation/TestXMLParser.swift
@@ -86,10 +86,10 @@
             return xmlUnderTest
         }
         if let open = encoding.range(of: "(") {
-            encoding = encoding.substring(from: open.upperBound)
+            encoding = String(encoding[open.upperBound...])
         }
         if let close = encoding.range(of: ")") {
-            encoding = encoding.substring(to: close.lowerBound)
+            encoding = String(encoding[..<close.lowerBound])
         }
         return "<?xml version='1.0' encoding='\(encoding.uppercased())' standalone='no'?>\n\(xmlUnderTest)\n"
     }
diff --git a/TestFoundation/main.swift b/TestFoundation/main.swift
index 6e288ac..9ae6d0f 100644
--- a/TestFoundation/main.swift
+++ b/TestFoundation/main.swift
@@ -73,7 +73,7 @@
     testCase(TestNSSet.allTests),
     testCase(TestStream.allTests),
     testCase(TestNSString.allTests),
-//    testCase(TestThread.allTests),
+    testCase(TestThread.allTests),
     testCase(TestProcess.allTests),
     testCase(TestNSTextCheckingResult.allTests),
     testCase(TestTimer.allTests),
@@ -104,4 +104,5 @@
     testCase(TestMassFormatter.allTests),
     testCase(TestJSONEncoder.allTests),
     testCase(TestCodable.allTests),
+    testCase(TestUnit.allTests),
 ])