Not sure what you have tried to solve here. sharedInstance works just fine in my test implementation with Xcode 8 beta 2:
Here is a portion of the implementation that does compile and work as expected, at least I couldn’t find any bugs. WARNING: the implementation we should tackle is here: https://gist.github.com/DevAndArtist/a5744f21107812b2d4e6baee2c55e0bf It differs how this is done in the following example: internal func _uniqueIdentifierOf(_ metatype: Any.Type) -> Int { return ObjectIdentifier.init(metatype).hashValue } public typealias Metatype<T> = T.Type public typealias AnyMetatype = Any.Type public final class Type<T> : Hashable { internal let _metatype: AnyMetatype internal init(metatype: AnyMetatype) { // check explicitly if `T` is `Any` let tIsAny = _uniqueIdentifierOf(Any.self) == _uniqueIdentifierOf(T.self) guard tIsAny || metatype is T.Type else { fatalError("'metatype' is not an instace of 'Metatype<T>'") } self._metatype = metatype } internal convenience init() { self.init(metatype: T.self) } public static func cast<U>(_ optionalType: Type<U>?) -> Type<T>? { guard let otherType = optionalType else { return nil } // Check if we can up- or downcast the metatype from `otherType` to `Metatype<T>` // Bug: SR-2085 // Workaround: Check explicitly if `T` is `Any` // let isTAny = _uniqueIdentifierOf(Any.self) == _uniqueIdentifierOf(T.self) guard isTAny || otherType._metatype is Metatype<T> else { return nil } return unsafeBitCast(otherType, to: Type<T>.self) } public var metatype: T.Type { return unsafeBitCast(self._metatype, to: T.Type.self) } public static var metatype: T.Type { return T.self } public var hashValue: Int { return _uniqueIdentifierOf(self._metatype) } } public func ==<T, U>(lhs: Type<T>, rhs: Type<U>) -> Bool { return lhs.hashValue == rhs.hashValue } internal var _typeStorage = Set<Type<Any>>() extension Type { internal static var sharedInstance: Type<T> { let identifier = _uniqueIdentifierOf(Type<T>.metatype) let typeFromStorage = _typeStorage.first(where: { $0.hashValue == identifier }) if let type = Type<T>.cast(typeFromStorage) { return type } let newType = Type<T>() // downcast `T` to `Any` if let type = Type<Any>.cast(newType) { _typeStorage.insert(type) } return newType } } Type<Int>.sharedInstance Type<Int>.sharedInstance Type<Int>.sharedInstance Type<Int>.sharedInstance print(_typeStorage) // [Type<Swift.Int>] Type<String>.sharedInstance print(_typeStorage) // [Type<Swift.Int>, Type<Swift.String>] class A {} class B: A {} Type<B>.sharedInstance Type<B>.sharedInstance print(_typeStorage) // [Type<Swift.Int>, Type<B>, Type<Swift.String>] Type<A>.sharedInstance print(_typeStorage) // [Type<Swift.String>, Type<Swift.Int>, Type<A>, Type<B>] -- Adrian Zubarev Sent with Airmail Am 15. Juli 2016 um 19:58:28, Anton Zhilin ([email protected]) schrieb: Consider what I said above, I feel like we should tackle this: drop init(_ copy: Type<T>) - to keep equality of Type<T> references Agreed. make all initializer internal and as exchange make sharedInstance public. This would ensure that you will always get a reference from the type storage, and that there can only exist one for each (dynamic) metatype. I have another idea: // No uniqueness guarantee internal class _Type<T> { var _metatype: Metatype<T> init() init(_: AnyMetatype) init?<U>(casting: Type<U>) // Instead of a global dictionary class var sharedInstance: _Type<T> } // Uniqueness guarantee public struct Type<T> { internal var impl: _Type<T> public init() public init(_: AnyMetatype) public init?<U>(casting: Type<U>) } I can’t foresee the future, so I’m wondering if the type may mutate somehow when reflections are added? I don’t think so. If added at all, types should only be able to be created using some kind of builder: let builder = TypeBuilder(name: "Person", kind: .struct) builder.addField(name: "", type: Int.self) //... let typeRef = builder.create()
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
