Alnitak Alnitak - 11 months ago 45
Swift Question

Swift block syntax failure to infer type

Can anyone explain why this single line block with an implicit


let r = withUnsafePointer(&msg) {
dn_expand(UnsafePointer($0), eomorig: UnsafePointer($0).advancedBy(msg.count), comp_dn: UnsafePointer($0).advancedBy(offset), exp_dn: &buf, length: buf.count)

but this version refactored where the only difference is to avoid the multiple calls to

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

with error message:

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

being called is just a trivial wrapper around

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)))


As already said in the comments, withUnsafePointer() is not the correct way to get a pointer to the element storage. It compiles, but gives unexpected results, as the following example demonstrates:

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

func foo(x: UnsafePointer<UInt8>) {

withUnsafePointer(&msg) {

This prints "random" numbers, but not the expected 1. The correct way is to call the withUnsafeBufferPointer() method on the array:

msg.withUnsafeBufferPointer {

In your case that would be

let r = msg.withUnsafeBufferPointer {
    dn_expand($0.baseAddress, eomorig: $0.baseAddress + $0.count, ...)

Here the return type of the closure is inferred automatically because it is a "single-expression" closure. If the closure contains more than one expression, you have to specify its type:

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

or let the compiler infer the return type from the context:

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