Swift 阻止语法推断类型失败

Swift block syntax failure to infer type

谁能解释为什么这个带有隐式 return 的单行块可以编译:

let r = withUnsafePointer(&msg) {
    dn_expand(UnsafePointer([=11=]), eomorig: UnsafePointer([=11=]).advancedBy(msg.count), comp_dn: UnsafePointer([=11=]).advancedBy(offset), exp_dn: &buf, length: buf.count)
}

但是这个版本进行了重构,唯一的区别是避免多次调用 UnsafePointer([=15=]) 而不是:

let s = withUnsafePointer(&msg) {
    let p = UnsafePointer([=12=])
    return dn_expand(p, eomorig: p.advancedBy(msg.count), comp_dn: p.advancedBy(offset), exp_dn: &buf, length: buf.count)
}

错误信息:

Cannot convert value of type 'inout [UInt8]' (aka 'inout Array<UInt8>') to expected argument type 'inout _'

被调用的 dn_function 只是 libresolvdn_expand 的简单包装:

public static func dn_expand(msg: UnsafePointer<UInt8>, eomorig: UnsafePointer<UInt8>, comp_dn: UnsafePointer<UInt8>, exp_dn: UnsafeMutablePointer<CChar>, length: Int) -> Int {
    return Int(res_9_dn_expand(msg, eomorig, comp_dn, exp_dn, Int32(length)))
}

如评论中所述,withUnsafePointer() 不是 获取指向元素存储的指针的正确方法。它编译,但是 给出意想不到的结果,如下例所示:

var msg: [UInt8] = [1, 2, 3, 4]

func foo(x: UnsafePointer<UInt8>) {
    print(x[0])
}

withUnsafePointer(&msg) {
    foo(UnsafePointer([=10=]))
}

这会打印 "random" 个数字,但不是预期的 1。正确的 方法是在数组上调用 withUnsafeBufferPointer() 方法:

msg.withUnsafeBufferPointer {
    foo([=11=].baseAddress)
}

你的情况是

let r = msg.withUnsafeBufferPointer {
    dn_expand([=12=].baseAddress, eomorig: [=12=].baseAddress + [=12=].count, ...)
}

这里闭包的 return 类型是自动推断的,因为 这是一个 "single-expression" 闭包。如果闭包包含更多 比一个表达式,你必须指定它的类型:

let r = msg.withUnsafeBufferPointer { bufPtr -> Int in
    let p = bufPtr.baseAddress
    return dn_expand(p, eomorig: p + msg.count, ...)
}

或者让编译器从 上下文推断 return 类型:

let r: Int = msg.withUnsafeBufferPointer { bufPtr in
    let p = bufPtr.baseAddress
    return dn_expand(p, eomorig: p + msg.count, ...)
}