奇数泛型;升级到iOS 12.2(Xcode 10.2)后Swift 4.2中的可选行为

奇数泛型;升级到iOS 12.2(Xcode 10.2)后Swift 4.2中的可选行为,swift,generics,optional,Swift,Generics,Optional,我们刚刚将Xcode更新为10.2(因此iOS 12.2 SDK),并开始看到与Swift泛型和Optionals相关的奇怪行为。我们将Swift版本保持在4.2,因此没有Swift 5更新。唯一的变化是从Xcode 10.1更新到Xcode 10.2 下面是一个示例代码,说明了这些奇怪之处。注释显示了版本之间的更改。理想情况下,不应该有任何变化 class Phone<T> {} extension Phone { class func create(initial: T

我们刚刚将Xcode更新为10.2(因此iOS 12.2 SDK),并开始看到与
Swift泛型
Optionals
相关的奇怪行为。我们将Swift版本保持在4.2,因此没有Swift 5更新。唯一的变化是从Xcode 10.1更新到Xcode 10.2

下面是一个示例代码,说明了这些奇怪之处。注释显示了版本之间的更改。理想情况下,不应该有任何变化

class Phone<T> {}

extension Phone {
    class func create(initial: T? = nil) -> Phone<T> {
        if let _ = initial { print("Regular: Unwrapping worked.") }
        return Phone()
    }
}

extension Phone where T == Void {
    class func create(initial: T? = nil) -> Phone<T> {
        if let _ = initial { print("T == Void: Unwrapping worked.") }
        return Phone()
    }
}

var phone: Phone<Int?> = Phone()
var phone2: Phone<Int?> = Phone()
var phone3: Phone<Int?> = Phone()

// unwrapping works iOS 12.1, doesn't work in 12.2
phone = Phone.create(initial: Optional(nil))

// unwrapping works iOS 12.1, doesn't work in 12.2
phone2 = Phone.create(initial: Optional<Int?>(nil))

// doesn't compile in iOS 12.1, unwrapping works in iOS 12.2
phone3 = Phone.create(initial: Optional<Int>(nil))

// doesn't compile in iOS 12.1, unwrapping doesn't work in 12.2 (uses the T == Void function)
let phone4 = Phone.create(initial: Optional(nil))
class电话{}
分机{
类func create(初始值:T?=nil)->Phone{
如果让uz=initial{print(“常规:展开工作”)}
回电
}
}
T==Void的分机{
类func create(初始值:T?=nil)->Phone{
如果让{print('T==Void:Unwrapping worked.)}
回电
}
}
var phone:phone=phone()
var phone2:Phone=Phone()
var phone3:Phone=Phone()
//在iOS 12.1中展开有效,但在12.2中不起作用
phone=phone.create(首字母:可选(无))
//在iOS 12.1中展开有效,但在12.2中不起作用
phone2=Phone.create(首字母:可选(无))
//不在iOS 12.1中编译,在iOS 12.2中展开工作
phone3=Phone.create(首字母:可选(无))
//在iOS 12.1中无法编译,在12.2中无法展开(使用t==Void函数)
让phone4=Phone.create(初始值:可选(无))
我们已经阅读了Xcode 10.2的发行说明,但没有发现关于可选或泛型的任何变化。很难理解是什么导致了不同版本之间行为的变化

特别有趣的是,
phone2
phone3
的行为方式不同。上面的代码示例中几乎没有奇怪的事情发生,因此问题是是否有人知道是什么导致了此版本中的行为更改?

这是因为这意味着
Optional(nil)
现在被编译器视为
nil as Optional
。以前使用
Optional(nil)
,您会得到一个包装的
nil
值,例如
Int???。一些(nil)
,但是现在您只得到
nil

因此,以下几点:

let phone: Phone<Int?> = Phone.create(initial: Optional(nil))
现在您正在向参数传递一个
Int???.some(nil)
,展开成功


然而,我想问你为什么要首先处理双重包装的期权——我强烈建议你避免使用它们,除非绝对必要。

我记得gereric optinals在4.2中改变了:不知道这是否是相对的,但我想我提到了……这太棒了@Hamish,非常感谢。我看到SE-0213在Swift 5中实现,为什么您认为我在完整的Swift 4.2代码库中看到了这一点?是时候使用苹果雷达了,还是我遗漏了什么?(我完全同意代码中的可选处理非常糟糕,这不是它应该采用的设计方式)。@Guven值得注意的是,SE-0213是在Swift 5编译器中实现的,而Swift 5编译器。似乎SE-0213的主要实现不考虑编译器正在运行的兼容模式,因此即使在SWIFT 4.2或4模式中也总是有效的。考虑到它可以巧妙地改变代码的行为,IMO认为这是错误的决定,并且应该通过版本检查来保护它。不幸的是,现在Swift 5已经发布,现在改变有点太晚了。
let phone: Phone<Int?> = Phone.create(initial: nil as Optional)
let phone: Phone<Int?> = Phone.create(initial: nil)
let phone: Phone<Int?> = Phone.create(initial: Optional.init(nil))