Merge remote-tracking branch 'origin/master' into swift-4.0-branch
diff --git a/Foundation/NSArray.swift b/Foundation/NSArray.swift
index 6f52df9..9c37357 100644
--- a/Foundation/NSArray.swift
+++ b/Foundation/NSArray.swift
@@ -446,9 +446,6 @@
         self.enumerateObjects(at: IndexSet(integersIn: 0..<count), options: opts, using: block)
     }
     open func enumerateObjects(at s: IndexSet, options opts: NSEnumerationOptions = [], using block: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
-        guard !opts.contains(.concurrent) else {
-            NSUnimplemented()
-        }
         s._bridgeToObjectiveC().enumerate(options: opts) { (idx, stop) in
             block(self.object(at: idx), idx, stop)
         }
diff --git a/Foundation/NSConcreteValue.swift b/Foundation/NSConcreteValue.swift
index 6b01414..eccb14e 100644
--- a/Foundation/NSConcreteValue.swift
+++ b/Foundation/NSConcreteValue.swift
@@ -39,7 +39,7 @@
                 
                 scanner.scanLocation = 1
                 
-                guard scanner.scanInteger(&count) && count > 0 else {
+                guard scanner.scanInt(&count) && count > 0 else {
                     print("NSConcreteValue.TypeInfo: array count is missing or zero")
                     return nil
                 }
diff --git a/Foundation/NSDictionary.swift b/Foundation/NSDictionary.swift
index 16ec60e..f331104 100644
--- a/Foundation/NSDictionary.swift
+++ b/Foundation/NSDictionary.swift
@@ -9,7 +9,7 @@
 
 
 import CoreFoundation
-
+import Dispatch
 
 open class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding {
     private let _cfinfo = _CFInfo(typeID: CFDictionaryGetTypeID())
@@ -454,19 +454,37 @@
         enumerateKeysAndObjects(options: [], using: block)
     }
 
-    open func enumerateKeysAndObjects(options opts: NSEnumerationOptions = [], using block: (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
+    open func enumerateKeysAndObjects(options opts: NSEnumerationOptions = [], using block: (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Void) {
         let count = self.count
         var keys = [Any]()
         var objects = [Any]()
+        var sharedStop = ObjCBool(false)
+        let lock = NSLock()
+        
         getObjects(&objects, andKeys: &keys, count: count)
-        var stop = ObjCBool(false)
-        for idx in 0..<count {
-            withUnsafeMutablePointer(to: &stop, { stop in
-                block(keys[idx], objects[idx], stop)
-            })
-
-            if stop {
-                break
+        let iteration: (Int) -> Void = withoutActuallyEscaping(block) { (closure: @escaping (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Void) -> (Int) -> Void in
+            return { (idx) in
+                lock.lock()
+                var stop = sharedStop
+                lock.unlock()
+                if stop { return }
+                
+                closure(keys[idx], objects[idx], &stop)
+                
+                if stop {
+                    lock.lock()
+                    sharedStop = stop
+                    lock.unlock()
+                    return
+                }
+            }
+        }
+        
+        if opts.contains(.concurrent) {
+            DispatchQueue.concurrentPerform(iterations: count, execute: iteration)
+        } else {
+            for idx in 0..<count {
+                iteration(idx)
             }
         }
     }
diff --git a/Foundation/NSGeometry.swift b/Foundation/NSGeometry.swift
index 9ac69d2..454014a 100644
--- a/Foundation/NSGeometry.swift
+++ b/Foundation/NSGeometry.swift
@@ -71,7 +71,7 @@
         return self.x.hashValue &+ self.y.hashValue
     }
     
-     var description: String? {
+     var description: String {
         return NSStringFromPoint(self)
     }
 }
@@ -134,7 +134,7 @@
         return self.width.hashValue &+ self.height.hashValue
     }
     
-    var description: String? {
+    var description: String {
         return NSStringFromSize(self)
     }
 }
@@ -216,7 +216,7 @@
         return self.origin.hash &+ self.size.hash
     }
     
-    var description: String? {
+    var description: String {
         return NSStringFromRect(self)
     }
 }
@@ -316,8 +316,8 @@
         return self.top.hashValue &+ self.left.hashValue &+ self.bottom.hashValue &+ self.right.hashValue
     }
     
-    var description: String? {
-        return nil
+    var description: String {
+        return ""
     }
 }
 
diff --git a/Foundation/NSIndexSet.swift b/Foundation/NSIndexSet.swift
index 6c5490d..66f2bf5 100644
--- a/Foundation/NSIndexSet.swift
+++ b/Foundation/NSIndexSet.swift
@@ -7,6 +7,7 @@
 // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 
+import Dispatch
 
 /* Class for managing set of indexes. The set of valid indexes are 0 .. NSNotFound - 1; trying to use indexes outside this range is an error.  NSIndexSet uses NSNotFound as a return value in cases where the queried index doesn't exist in the set; for instance, when you ask firstIndex and there are no indexes; or when you ask for indexGreaterThanIndex: on the last index, and so on.
 
@@ -388,36 +389,60 @@
         let reverse = opts.contains(.reverse)
         let passRanges = paramType == NSRange.self
         let findIndex = returnType == Bool.self
-        var stop = false
+        var sharedStop = false
+        let lock = NSLock()
         let ranges = _ranges[startRangeIndex...endRangeIndex]
-        let rangeSequence = (reverse ? AnySequence(ranges.reversed()) : AnySequence(ranges))
-        outer: for curRange in rangeSequence {
-            let intersection = NSIntersectionRange(curRange, range)
-            if passRanges {
-                if intersection.length > 0 {
-                    let _ = block(intersection as! P, &stop)
-                }
-                if stop {
-                    break outer
-                }
-            } else if intersection.length > 0 {
-                let maxIndex = NSMaxRange(intersection) - 1
-                let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1)
-                for idx in indexes {
-                    if findIndex {
-                        let found : Bool = block(idx as! P, &stop) as! Bool
-                        if found {
-                            result = idx
-                            stop = true
-                        }
-                    } else {
-                        let _ = block(idx as! P, &stop)
+        let rangeSequence = (reverse ? AnyCollection(ranges.reversed()) : AnyCollection(ranges))
+        let iteration = withoutActuallyEscaping(block) { (closure: @escaping (P, UnsafeMutablePointer<ObjCBool>) -> R) -> (Int) -> Void in
+            return { (rangeIdx) in
+                lock.lock()
+                var stop = sharedStop
+                lock.unlock()
+                if stop { return }
+                
+                let idx = rangeSequence.index(rangeSequence.startIndex, offsetBy: IntMax(rangeIdx))
+                let curRange = rangeSequence[idx]
+                let intersection = NSIntersectionRange(curRange, range)
+                if passRanges {
+                    if intersection.length > 0 {
+                        let _ = closure(intersection as! P, &stop)
                     }
                     if stop {
-                        break outer
+                        lock.lock()
+                        sharedStop = stop
+                        lock.unlock()
+                        return
+                    }
+                } else if intersection.length > 0 {
+                    let maxIndex = NSMaxRange(intersection) - 1
+                    let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1)
+                    for idx in indexes {
+                        if findIndex {
+                            let found : Bool = closure(idx as! P, &stop) as! Bool
+                            if found {
+                                result = idx
+                                stop = true
+                            }
+                        } else {
+                            let _ = closure(idx as! P, &stop)
+                        }
+                        if stop {
+                            lock.lock()
+                            sharedStop = stop
+                            lock.unlock()
+                            return
+                        }
                     }
                 }
-            } // else, continue
+            }
+        }
+        
+        if opts.contains(.concurrent) {
+            DispatchQueue.concurrentPerform(iterations: Int(rangeSequence.count), execute: iteration)
+        } else {
+            for idx in 0..<Int(rangeSequence.count) {
+                iteration(idx)
+            }
         }
         
         return result
diff --git a/Foundation/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift
index 40fc5a5..3790990 100644
--- a/Foundation/NSKeyedArchiver.swift
+++ b/Foundation/NSKeyedArchiver.swift
@@ -755,7 +755,7 @@
             scanner.scanLocation = 1 // advance past ObJCType
             
             var count : Int = 0
-            guard scanner.scanInteger(&count) && count > 0 else {
+            guard scanner.scanInt(&count) && count > 0 else {
                 fatalError("NSKeyedArchiver.encodeValueOfObjCType: array count is missing or zero")
             }
             
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index c8feeb5..47fc2f8 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -813,7 +813,7 @@
             scanner.scanLocation = 1
             
             var count : Int = 0
-            guard scanner.scanInteger(&count) && count > 0 else {
+            guard scanner.scanInt(&count) && count > 0 else {
                 fatalError("NSKeyedUnarchiver.decodeValueOfObjCType: array count is missing or zero")
             }
             
diff --git a/Foundation/NSRange.swift b/Foundation/NSRange.swift
index 5889644..699ebb1 100644
--- a/Foundation/NSRange.swift
+++ b/Foundation/NSRange.swift
@@ -7,11 +7,15 @@
 // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 
+#if DEPLOYMENT_RUNTIME_SWIFT
+
 import CoreFoundation
 
 public struct _NSRange {
     public var location: Int
     public var length: Int
+    
+    
     public init() {
         location = 0
         length = 0
@@ -21,100 +25,10 @@
         self.location = location
         self.length = length
     }
+}
     
-    internal init(_ range: CFRange) {
-        location = range.location == kCFNotFound ? NSNotFound : range.location
-        length = range.length
-    }
-}
-
-extension CFRange {
-    internal init(_ range: NSRange) {
-        location = range.location == NSNotFound ? kCFNotFound : range.location
-        length = range.length
-    }
-}
-
 public typealias NSRange = _NSRange
-
-extension NSRange {
-    public init(_ x: Range<Int>) {
-        location = x.lowerBound
-        length = x.count
-    }
     
-    public func toRange() -> Range<Int>? {
-        if location == NSNotFound { return nil }
-        return location..<(location+length)
-    }
-    
-    internal func toCountableRange() -> CountableRange<Int>? {
-        if location == NSNotFound { return nil }
-        return location..<(location+length)
-    }
-}
-
-extension NSRange: NSSpecialValueCoding {
-    init(bytes: UnsafeRawPointer) {
-        self.location = bytes.load(as: Int.self)
-        self.length = bytes.load(fromByteOffset: MemoryLayout<Int>.stride, as: Int.self)
-    }
-    
-    init?(coder aDecoder: NSCoder) {
-        guard aDecoder.allowsKeyedCoding else {
-            preconditionFailure("Unkeyed coding is unsupported.")
-        }
-        if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") {
-            self.location = location.intValue
-        } else {
-            self.location = 0
-        }
-        if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") {
-            self.length = length.intValue
-        } else {
-            self.length = 0
-        }
-    }
-
-    func encodeWithCoder(_ aCoder: NSCoder) {
-        guard aCoder.allowsKeyedCoding else {
-            preconditionFailure("Unkeyed coding is unsupported.")
-        }
-        aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location")
-        aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length")
-    }
-    
-    static func objCType() -> String {
-#if arch(i386) || arch(arm)
-        return "{_NSRange=II}"
-#elseif arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
-        return "{_NSRange=QQ}"
-#else
-        NSUnimplemented()
-#endif
-    }
-    
-    func getValue(_ value: UnsafeMutableRawPointer) {
-        value.initializeMemory(as: NSRange.self, to: self)
-    }
-    
-    func isEqual(_ aValue: Any) -> Bool {
-        if let other = aValue as? NSRange {
-            return other.location == self.location && other.length == self.length
-        } else {
-            return false
-        }
-    }
-    
-    var hash: Int {
-        return self.location &+ self.length
-    }
-    
-    var description: String? {
-        return NSStringFromRange(self)
-    }
-}
-
 public typealias NSRangePointer = UnsafeMutablePointer<NSRange>
 
 public func NSMakeRange(_ loc: Int, _ len: Int) -> NSRange {
@@ -185,7 +99,7 @@
         // fail early if there are no decimal digits
         return emptyRange
     }
-    guard let location = scanner.scanInteger() else {
+    guard let location = scanner.scanInt() else {
         return emptyRange
     }
     let partialRange = NSMakeRange(location, 0)
@@ -198,12 +112,308 @@
         // return early if there are no integer characters after the first int in the string
         return partialRange
     }
-    guard let length = scanner.scanInteger() else {
+    guard let length = scanner.scanInt() else {
         return partialRange
     }
     return NSMakeRange(location, length)
 }
+    
+#else
+@_exported import Foundation // Clang module
+#endif
 
+extension NSRange : Hashable {
+    public var hashValue: Int {
+        #if arch(i386) || arch(arm)
+            return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 16)))
+        #elseif arch(x86_64) || arch(arm64)
+            return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 32)))
+        #endif
+    }
+    
+    public static func==(_ lhs: NSRange, _ rhs: NSRange) -> Bool {
+        return lhs.location == rhs.location && lhs.length == rhs.length
+    }
+}
+
+extension NSRange : CustomStringConvertible, CustomDebugStringConvertible {
+    public var description: String { return "{\(location), \(length)}" }
+    public var debugDescription: String {
+        guard location != NSNotFound else {
+            return "{NSNotFound, \(length)}"
+        }
+        return "{\(location), \(length)}"
+    }
+}
+
+extension NSRange {
+    public init?(_ string: String) {
+        var savedLocation = 0
+        if string.isEmpty {
+            // fail early if the string is empty
+            return nil
+        }
+        let scanner = Scanner(string: string)
+        let digitSet = CharacterSet.decimalDigits
+        let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
+        if scanner.isAtEnd {
+            // fail early if there are no decimal digits
+            return nil
+        }
+        var location = 0
+        savedLocation = scanner.scanLocation
+        guard scanner.scanInt(&location) else {
+            return nil
+        }
+        if scanner.isAtEnd {
+            // return early if there are no more characters after the first int in the string
+            return nil
+        }
+        if scanner.scanString(".", into: nil) {
+            scanner.scanLocation = savedLocation
+            var double = 0.0
+            guard scanner.scanDouble(&double) else {
+                return nil
+            }
+            guard let integral = Int(exactly: double) else {
+                return nil
+            }
+            location = integral
+        }
+        
+        let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
+        if scanner.isAtEnd {
+            // return early if there are no integer characters after the first int in the string
+            return nil
+        }
+        var length = 0
+        savedLocation = scanner.scanLocation
+        guard scanner.scanInt(&length) else {
+            return nil
+        }
+        
+        if !scanner.isAtEnd {
+            if scanner.scanString(".", into: nil) {
+                scanner.scanLocation = savedLocation
+                var double = 0.0
+                guard scanner.scanDouble(&double) else {
+                    return nil
+                }
+                guard let integral = Int(exactly: double) else {
+                    return nil
+                }
+                length = integral
+            }
+        }
+        
+        
+        self.location = location
+        self.length = length
+    }
+}
+
+extension NSRange {
+    public var lowerBound: Int { return location }
+    
+    public var upperBound: Int { return location + length }
+    
+    public func contains(_ index: Int) -> Bool { return (!(index < location) && (index - location) < length) }
+    
+    public mutating func formUnion(_ other: NSRange) {
+        self = union(other)
+    }
+    
+    public func union(_ other: NSRange) -> NSRange {
+        let max1 = location + length
+        let max2 = other.location + other.length
+        let maxend = (max1 < max2) ? max2 : max1
+        let minloc = location < other.location ? location : other.location
+        return NSRange(location: minloc, length: maxend - minloc)
+    }
+    
+    public func intersection(_ other: NSRange) -> NSRange? {
+        let max1 = location + length
+        let max2 = other.location + other.length
+        let minend = (max1 < max2) ? max1 : max2
+        if other.location <= location && location < max2 {
+            return NSRange(location: location, length: minend - location)
+        } else if location <= other.location && other.location < max1 {
+            return NSRange(location: other.location, length: minend - other.location);
+        }
+        return nil
+    }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Ranges
+//===----------------------------------------------------------------------===//
+
+extension NSRange {
+    public init<R: RangeExpression>(_ region: R)
+        where R.Bound: FixedWidthInteger, R.Bound.Stride : SignedInteger {
+            let r = region.relative(to: 0..<R.Bound.max)
+            location = numericCast(r.lowerBound)
+            length = numericCast(r.count)
+    }
+    
+    public init<R: RangeExpression, S: StringProtocol>(_ region: R, in target: S)
+        where R.Bound == S.Index, S.Index == String.Index {
+            let r = region.relative(to: target)
+            self = NSRange(
+                location: r.lowerBound._utf16Index - target.startIndex._utf16Index,
+                length: r.upperBound._utf16Index - r.lowerBound._utf16Index
+            )
+    }
+    
+    @available(swift, deprecated: 4, renamed: "Range.init(_:)")
+    public func toRange() -> Range<Int>? {
+        if location == NSNotFound { return nil }
+        return location..<(location+length)
+    }
+}
+
+extension Range where Bound: BinaryInteger {
+    public init?(_ range: NSRange) {
+        guard range.location != NSNotFound else { return nil }
+        self.init(uncheckedBounds: (numericCast(range.lowerBound), numericCast(range.upperBound)))
+    }
+}
+
+// This additional overload will mean Range.init(_:) defaults to Range<Int> when
+// no additional type context is provided:
+extension Range where Bound == Int {
+    public init?(_ range: NSRange) {
+        guard range.location != NSNotFound else { return nil }
+        self.init(uncheckedBounds: (range.lowerBound, range.upperBound))
+    }
+}
+
+extension Range where Bound == String.Index {
+    public init?(_ range: NSRange, in string: String) {
+        let u = string.utf16
+        guard range.location != NSNotFound,
+            let start = u.index(u.startIndex, offsetBy: range.location, limitedBy: u.endIndex),
+            let end = u.index(u.startIndex, offsetBy: range.location + range.length, limitedBy: u.endIndex),
+            let lowerBound = String.Index(start, within: string),
+            let upperBound = String.Index(end, within: string)
+            else { return nil }
+        
+        self = lowerBound..<upperBound
+    }
+}
+
+extension NSRange : CustomReflectable {
+    public var customMirror: Mirror {
+        return Mirror(self, children: ["location": location, "length": length])
+    }
+}
+
+extension NSRange : CustomPlaygroundQuickLookable {
+    public var customPlaygroundQuickLook: PlaygroundQuickLook {
+        return .range(Int64(location), Int64(length))
+    }
+}
+
+extension NSRange : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let location = try container.decode(Int.self)
+        let length = try container.decode(Int.self)
+        self.init(location: location, length: length)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(self.location)
+        try container.encode(self.length)
+    }
+}
+
+#if DEPLOYMENT_RUNTIME_SWIFT
+
+    
+extension NSRange {
+    internal init(_ range: CFRange) {
+        location = range.location == kCFNotFound ? NSNotFound : range.location
+        length = range.length
+    }
+}
+    
+extension CFRange {
+    internal init(_ range: NSRange) {
+        location = range.location == NSNotFound ? kCFNotFound : range.location
+        length = range.length
+    }
+}
+    
+extension NSRange {
+    public init(_ x: Range<Int>) {
+        location = x.lowerBound
+        length = x.count
+    }
+    
+    internal func toCountableRange() -> CountableRange<Int>? {
+        if location == NSNotFound { return nil }
+        return location..<(location+length)
+    }
+}
+    
+extension NSRange: NSSpecialValueCoding {
+    init(bytes: UnsafeRawPointer) {
+        self.location = bytes.load(as: Int.self)
+        self.length = bytes.load(fromByteOffset: MemoryLayout<Int>.stride, as: Int.self)
+    }
+    
+    init?(coder aDecoder: NSCoder) {
+        guard aDecoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") {
+            self.location = location.intValue
+        } else {
+            self.location = 0
+        }
+        if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") {
+            self.length = length.intValue
+        } else {
+            self.length = 0
+        }
+    }
+    
+    func encodeWithCoder(_ aCoder: NSCoder) {
+        guard aCoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location")
+        aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length")
+    }
+    
+    static func objCType() -> String {
+#if arch(i386) || arch(arm)
+        return "{_NSRange=II}"
+#elseif arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+        return "{_NSRange=QQ}"
+#else
+        NSUnimplemented()
+#endif
+    }
+    
+    func getValue(_ value: UnsafeMutableRawPointer) {
+        value.initializeMemory(as: NSRange.self, to: self)
+    }
+    
+    func isEqual(_ aValue: Any) -> Bool {
+        if let other = aValue as? NSRange {
+            return other.location == self.location && other.length == self.length
+        } else {
+            return false
+        }
+    }
+    
+    var hash: Int { return hashValue }
+}
+    
 extension NSValue {
     public convenience init(range: NSRange) {
         self.init()
@@ -215,3 +425,5 @@
         return specialValue._value as! NSRange
     }
 }
+#endif
+
diff --git a/Foundation/NSScanner.swift b/Foundation/NSScanner.swift
index 93b91ea..40da664 100644
--- a/Foundation/NSScanner.swift
+++ b/Foundation/NSScanner.swift
@@ -391,19 +391,19 @@
 extension Scanner {
     
     // On overflow, the below methods will return success and clamp
-    public func scanInt(_ result: UnsafeMutablePointer<Int32>) -> Bool {
+    public func scanInt32(_ result: UnsafeMutablePointer<Int32>) -> Bool {
         return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int32) -> Void in
             result.pointee = value
         }
     }
     
-    public func scanInteger(_ result: UnsafeMutablePointer<Int>) -> Bool {
+    public func scanInt(_ result: UnsafeMutablePointer<Int>) -> Bool {
         return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int) -> Void in
             result.pointee = value
         }
     }
     
-    public func scanLongLong(_ result: UnsafeMutablePointer<Int64>) -> Bool {
+    public func scanInt64(_ result: UnsafeMutablePointer<Int64>) -> Bool {
         return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int64) -> Void in
             result.pointee = value
         }
@@ -427,13 +427,13 @@
         }
     }
     
-    public func scanHexInt(_ result: UnsafeMutablePointer<UInt32>) -> Bool {
+    public func scanHexInt32(_ result: UnsafeMutablePointer<UInt32>) -> Bool {
         return _scanString.scanHex(_skipSet, locationToScanFrom: &_scanLocation) { (value: UInt32) -> Void in
             result.pointee = value
         }
     }
     
-    public func scanHexLongLong(_ result: UnsafeMutablePointer<UInt64>) -> Bool {
+    public func scanHexInt64(_ result: UnsafeMutablePointer<UInt64>) -> Bool {
         return _scanString.scanHex(_skipSet, locationToScanFrom: &_scanLocation) { (value: UInt64) -> Void in
             result.pointee = value
         }
@@ -469,9 +469,20 @@
 /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative
 /// - Note: Since this API is under consideration it may be either removed or revised in the near future
 extension Scanner {
-    public func scanInt() -> Int32? {
+    public func scanInt32() -> Int32? {
         var value: Int32 = 0
         return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int32>) -> Int32? in
+            if scanInt32(ptr) {
+                return ptr.pointee
+            } else {
+                return nil
+            }
+        }
+    }
+    
+    public func scanInt() -> Int? {
+        var value: Int = 0
+        return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int>) -> Int? in
             if scanInt(ptr) {
                 return ptr.pointee
             } else {
@@ -480,21 +491,10 @@
         }
     }
     
-    public func scanInteger() -> Int? {
-        var value: Int = 0
-        return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int>) -> Int? in
-            if scanInteger(ptr) {
-                return ptr.pointee
-            } else {
-                return nil
-            }
-        }
-    }
-    
-    public func scanLongLong() -> Int64? {
+    public func scanInt64() -> Int64? {
         var value: Int64 = 0
         return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int64>) -> Int64? in
-            if scanLongLong(ptr) {
+            if scanInt64(ptr) {
                 return ptr.pointee
             } else {
                 return nil
@@ -535,10 +535,10 @@
         }
     }
     
-    public func scanHexInt() -> UInt32? {
+    public func scanHexInt32() -> UInt32? {
         var value: UInt32 = 0
         return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<UInt32>) -> UInt32? in
-            if scanHexInt(ptr) {
+            if scanHexInt32(ptr) {
                 return ptr.pointee
             } else {
                 return nil
@@ -546,10 +546,10 @@
         }
     }
     
-    public func scanHexLongLong() -> UInt64? {
+    public func scanHexInt64() -> UInt64? {
         var value: UInt64 = 0
         return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<UInt64>) -> UInt64? in
-            if scanHexLongLong(ptr) {
+            if scanHexInt64(ptr) {
                 return ptr.pointee
             } else {
                 return nil
@@ -579,9 +579,17 @@
         }
     }
     
+    public func scanString(_ string:String, into ptr: UnsafeMutablePointer<String?>?) -> Bool {
+        if let str = scanString(string) {
+            ptr?.pointee = str
+            return true
+        }
+        return false
+    }
+    
     // These methods avoid calling the private API for _invertedSkipSet and manually re-construct them so that it is only usage of public API usage
     // Future implementations on Darwin of these methods will likely be more optimized to take advantage of the cached values.
-    public func scanString(string searchString: String) -> String? {
+    public func scanString(_ searchString: String) -> String? {
         let str = self.string._bridgeToObjectiveC()
         var stringLoc = scanLocation
         let stringLen = str.length
@@ -644,6 +652,14 @@
         return nil
     }
     
+    public func scanUpToCharacters(from set: CharacterSet, into ptr: UnsafeMutablePointer<String?>?) -> Bool {
+        if let result = scanUpToCharactersFromSet(set) {
+            ptr?.pointee = result
+            return true
+        }
+        return false
+    }
+    
     public func scanUpToCharactersFromSet(_ set: CharacterSet) -> String? {
         let str = self.string._bridgeToObjectiveC()
         var stringLoc = scanLocation
diff --git a/Foundation/NSSpecialValue.swift b/Foundation/NSSpecialValue.swift
index 42bc6d9..6809db0 100644
--- a/Foundation/NSSpecialValue.swift
+++ b/Foundation/NSSpecialValue.swift
@@ -25,7 +25,7 @@
     // So in order to implement equality and hash we have the hack below.
     func isEqual(_ value: Any) -> Bool
     var hash: Int { get }
-    var description: String? { get }
+    var description: String { get }
 }
 
 internal class NSSpecialValue : NSValue {
@@ -126,11 +126,11 @@
     }
     
     override var description : String {
-        if let description = _value.description {
-            return description
-        } else {
+        let desc = _value.description
+        if desc.isEmpty {
             return super.description
         }
+        return desc
     }
     
     override func isEqual(_ value: Any?) -> Bool {
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index a444c24..97212d5 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -639,18 +639,18 @@
     }
 
     public var intValue: Int32 {
-        return Scanner(string: _swiftObject).scanInt() ?? 0
+        return Scanner(string: _swiftObject).scanInt32() ?? 0
     }
 
     public var integerValue: Int {
         let scanner = Scanner(string: _swiftObject)
         var value: Int = 0
-        let _ = scanner.scanInteger(&value)
+        let _ = scanner.scanInt(&value)
         return value
     }
 
     public var longLongValue: Int64 {
-        return Scanner(string: _swiftObject).scanLongLong() ?? 0
+        return Scanner(string: _swiftObject).scanInt64() ?? 0
     }
 
     public var boolValue: Bool {
@@ -658,8 +658,8 @@
         // skip initial whitespace if present
         let _ = scanner.scanCharactersFromSet(.whitespaces)
         // scan a single optional '+' or '-' character, followed by zeroes
-        if scanner.scanString(string: "+") == nil {
-            let _ = scanner.scanString(string: "-")
+        if scanner.scanString("+") == nil {
+            let _ = scanner.scanString("-")
         }
         // scan any following zeroes
         let _ = scanner.scanCharactersFromSet(CharacterSet(charactersIn: "0"))
diff --git a/TestFoundation/TestNSScanner.swift b/TestFoundation/TestNSScanner.swift
index 4ed0ded..aec488d 100644
--- a/TestFoundation/TestNSScanner.swift
+++ b/TestFoundation/TestNSScanner.swift
@@ -33,7 +33,7 @@
     func test_scanInteger() {
         let scanner = Scanner(string: "123")
         var value: Int = 0
-        XCTAssert(scanner.scanInteger(&value), "An Integer should be found in the string `123`.")
+        XCTAssert(scanner.scanInt(&value), "An Integer should be found in the string `123`.")
         XCTAssertEqual(value, 123, "Scanned Integer value of the string `123` should be `123`.")
         XCTAssertTrue(scanner.isAtEnd)
     }
@@ -48,7 +48,7 @@
     func test_scanString() {
         let scanner = Scanner(string: "apple sauce")
 
-        guard let firstPart = scanner.scanString(string: "apple ") else {
+        guard let firstPart = scanner.scanString("apple ") else {
             XCTFail()
             return
         }
@@ -56,7 +56,7 @@
         XCTAssertEqual(firstPart, "apple ")
         XCTAssertFalse(scanner.isAtEnd)
 
-        let _ = scanner.scanString(string: "sauce")
+        let _ = scanner.scanString("sauce")
         XCTAssertTrue(scanner.isAtEnd)
     }
 
@@ -64,7 +64,7 @@
         let scanner = Scanner(string: "xyz  ")
         scanner.charactersToBeSkipped = .whitespaces
 
-        let _ = scanner.scanString(string: "xyz")
+        let _ = scanner.scanString("xyz")
         XCTAssertTrue(scanner.isAtEnd)
     }
 }