Swift @autoclosure评估受类型注释的影响? (编译器错误?)

时间:2015-01-17 20:44:51

标签: swift typechecking compiler-bug

我今天再次使用Swift,需要undefined()功能。基本上是一个函数,可以是您想要的任何类型,但在实际运行/评估时崩溃。如果您还没有时间实现某个表达式,但希望查看程序类型是否有效,那么这很有用。

我还实施了一个Result<T>和一个(可疑的)函数chain,如果不成功则返回左Result<>,否则返回右Result<>。因此,签名为chain<L,R>(l : Result<L>, r : @autoclosure () -> Result<R>) -> Result<R>。我将权限Result<>定义为@autoclosure,因为如果左边是失败,则无需对其进行评估。

我对这些内容的有用性(或改进)不感兴趣,我只是对我的程序在标记为[L3]的行中崩溃感兴趣。

请注意

  • 按预期[L1]正常工作(||是懒惰评估的)
  • [L2]工作正常(chain在其正确的论证中也很懒惰)

但是,奇怪的是

  • [L3]崩溃评估undefined()
  • 的程序

根据我的理解,L2和L3在运行时应该是等价的:L3只是告诉类型检查器它已经知道的东西......如果你将undefined的类型更改为{{() -> Result<T>,那么同样的效果会发生1}}(而不是() -> T),即使没有as Result<String>,它也能正常工作。

这是我的全部代码:

import Foundation

enum Result<T> {
    case Success(@autoclosure () -> T);
    case Failure(@autoclosure () -> NSError)
}

func undefined<T>(file:StaticString=__FILE__, line:UWord=__LINE__) -> T {
    fatalError("undefined", file:file, line:line)
}

func chain<L,R>(l : Result<L>, r : @autoclosure () -> Result<R>) -> Result<R> {
    switch(l) {
    case .Failure(let f):
        return .Failure(f())
    case .Success(let _):
        return r()
    }
}

func testEvaluation() {
    let error = NSError(domain: NSPOSIXErrorDomain, code: Int(ENOENT), userInfo: nil)
    let failure : Result<String> = .Failure(error)
    assert(true || undefined() as Bool) // [L1]: works
    let x : Result<String> = chain(failure, undefined() as Result<String>) // [L2]: works
    print("x = \(x)\n")
    let y : Result<String> = chain(failure, undefined()) // [L3]: CRASHES THE PROGRAM EVALUATING undefined()
    print("y = \(y)\n")
}

testEvaluation()

信不信由你,程序的输出是:

x = (Enum Value)
fatal error: undefined: file main.swift, line 27
Illegal instruction: 4

那不对!为什么as Result<String>(这是L2和L3之间的唯一区别)会改变程序的输出?这应该在类型检查器中完全处理,这意味着在编译时,不是吗?编译错误?

重现这一点的最快方法应该是:

  1. 将我的所有代码复制到剪贴板
  2. cd /tmp
  3. pbpaste > main.swift
  4. xcrun -sdk macosx swiftc main.swift
  5. ./main
  6. 实际输出:

    x = (Enum Value)
    fatal error: undefined: file main.swift, line 27
    Illegal instruction: 4
    

    预期产出:

    x = (Enum Value)
    y = (Enum Value)
    

1 个答案:

答案 0 :(得分:0)

Swift开发人员Joe Groff via Twitter确认为一个错误。