| //===----------------------------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // FIXME(ABI)(compiler limitation): This protocol exists to identify |
| // `AnyHashable` in conditional extensions. Replace this protocol |
| // with conditional extensions on `Set` and `Dictionary` "where Key == |
| // AnyHashable". |
| public protocol _AnyHashableProtocol { |
| var base: Any { get } |
| } |
| |
| extension AnyHashable : _AnyHashableProtocol {} |
| |
| //===----------------------------------------------------------------------===// |
| // Convenience APIs for Set<AnyHashable> |
| //===----------------------------------------------------------------------===// |
| |
| // FIXME: remove these trampolines when extensions below can be |
| // properly expressed in the language. |
| extension Set { |
| @inline(__always) |
| internal mutating func _concreteElement_insert( |
| _ newMember: Element |
| ) -> (inserted: Bool, memberAfterInsert: Element) { |
| return insert(newMember) |
| } |
| |
| @inline(__always) |
| internal mutating func _concreteElement_update( |
| with newMember: Element |
| ) -> Element? { |
| return update(with: newMember) |
| } |
| |
| @inline(__always) |
| internal mutating func _concreteElement_remove( |
| _ member: Element |
| ) -> Element? { |
| return remove(member) |
| } |
| } |
| |
| // FIXME(ABI)(compiler limitation): replace with `where Element == AnyHashable`. |
| extension Set where Element : _AnyHashableProtocol { |
| public mutating func insert<ConcreteElement : Hashable>( |
| _ newMember: ConcreteElement |
| ) -> (inserted: Bool, memberAfterInsert: ConcreteElement) { |
| let (inserted, memberAfterInsert) = |
| _concreteElement_insert(AnyHashable(newMember) as! Element) |
| return ( |
| inserted: inserted, |
| memberAfterInsert: memberAfterInsert.base as! ConcreteElement) |
| } |
| |
| @discardableResult |
| public mutating func update<ConcreteElement : Hashable>( |
| with newMember: ConcreteElement |
| ) -> ConcreteElement? { |
| return _concreteElement_update(with: AnyHashable(newMember) as! Element) |
| .map { $0.base as! ConcreteElement } |
| } |
| |
| @discardableResult |
| public mutating func remove<ConcreteElement : Hashable>( |
| _ member: ConcreteElement |
| ) -> ConcreteElement? { |
| return _concreteElement_remove(AnyHashable(member) as! Element) |
| .map { $0.base as! ConcreteElement } |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Convenience APIs for Dictionary<AnyHashable, *> |
| //===----------------------------------------------------------------------===// |
| |
| // FIXME: remove these trampolines when extensions below can be |
| // properly expressed in the language. |
| extension Dictionary { |
| internal subscript(_concreteKey key: Key) -> Value? { |
| @inline(__always) |
| get { |
| return self[key] |
| } |
| @inline(__always) |
| set(newValue) { |
| self[key] = newValue |
| } |
| } |
| |
| @inline(__always) |
| internal mutating func _concreteKey_updateValue( |
| _ value: Value, forKey key: Key |
| ) -> Value? { |
| return updateValue(value, forKey: key) |
| } |
| |
| @inline(__always) |
| internal mutating func _concreteKey_removeValue(forKey key: Key) -> Value? { |
| return removeValue(forKey: key) |
| } |
| } |
| |
| // FIXME(ABI)(compiler limitation): replace with `where Element == AnyHashable`. |
| extension Dictionary where Key : _AnyHashableProtocol { |
| public subscript(_ key: _Hashable) -> Value? { |
| // FIXME(ABI)(compiler limitation): replace this API with a |
| // generic subscript. |
| get { |
| return self[_concreteKey: key._toAnyHashable() as! Key] |
| } |
| set { |
| self[_concreteKey: key._toAnyHashable() as! Key] = newValue |
| } |
| } |
| |
| @discardableResult |
| public mutating func updateValue<ConcreteKey : Hashable>( |
| _ value: Value, forKey key: ConcreteKey |
| ) -> Value? { |
| return _concreteKey_updateValue(value, forKey: AnyHashable(key) as! Key) |
| } |
| |
| @discardableResult |
| public mutating func removeValue<ConcreteKey : Hashable>( |
| forKey key: ConcreteKey |
| ) -> Value? { |
| return _concreteKey_removeValue(forKey: AnyHashable(key) as! Key) |
| } |
| } |
| |