IUO from C Library Interface


(Ryan Lovelett) #1

import CommonCrypto

protocol Foo {
  associatedtype Context
  var context: Context { get set }
  var bar: (UnsafeMutablePointer<Context>!, UnsafeRawPointer!, CC_LONG)
  -> Int32 { get }
}

struct SHA1: Foo {
  var context: CC_SHA1_CTX
  var bar: (UnsafeMutablePointer<CC_SHA1_CTX>!, UnsafeRawPointer!,
  CC_LONG) -> Int32 = CC_SHA1_Update
}

Unfortunately this will not compile any longer with Swift 3.0. The error
is: Implicitly unwrapped optionals are only allowed at top level and as
function results.

I can try modifying `bar` definition to be `?` instead of `!` but then
`CC_SHA1_Update`) can no longer be assigned to `bar`.

Suggestions?


(Joe Groff) #2

Not being able to assign the function reference is a bug. As a workaround, you should be able to unsafeBitCast CC_SHA1_Update to the appropriate type.

-Joe

···

On Oct 24, 2016, at 2:24 PM, Ryan Lovelett via swift-users <swift-users@swift.org> wrote:

import CommonCrypto

protocol Foo {
associatedtype Context
var context: Context { get set }
var bar: (UnsafeMutablePointer<Context>!, UnsafeRawPointer!, CC_LONG)
-> Int32 { get }
}

struct SHA1: Foo {
var context: CC_SHA1_CTX
var bar: (UnsafeMutablePointer<CC_SHA1_CTX>!, UnsafeRawPointer!,
CC_LONG) -> Int32 = CC_SHA1_Update
}

Unfortunately this will not compile any longer with Swift 3.0. The error
is: Implicitly unwrapped optionals are only allowed at top level and as
function results.

I can try modifying `bar` definition to be `?` instead of `!` but then
`CC_SHA1_Update`) can no longer be assigned to `bar`.

Suggestions?


(Ryan Lovelett) #3

Not being able to assign the function reference is a bug. As a
workaround, you should be able to unsafeBitCast CC_SHA1_Update to the
appropriate type.

-Joe

Two questions:

1. Is this an already reported bug? If so, would you happen to know what
it is so I can track it for resolution (to remove the work-around when
it is resolved)?

I made the protocol def this:
var bar: (UnsafeMutablePointer<Context>?, UnsafeRawPointer?, CC_LONG) ->
Int32 { get }

Then the imp this:
let bar = unsafeBitCast(CC_SHA1_Update, to:
((UnsafeMutablePointer<CC_SHA1_CTX>?, UnsafeRawPointer?, CC_LONG) ->
Int32).self)

2. Perhaps I'm doing something wrong here but I feel like this just make
the code less safe. It seems now I can send in an optional, read: nil,
pointer to this `bar` method. On face, this seems dangerous. The
`CC_SHA1_Update` method seems explicit in that it will not deal with
`nil`. So it seems that this thing is now reporting a safer API than
what is actually there. Or did I misunderstand? Should I be dropping the
IUO all together and just make it `UnsafeMutablePointer<Context>` and
`UnsafeRawPointer`?


(Joe Groff) #4

Not being able to assign the function reference is a bug. As a
workaround, you should be able to unsafeBitCast CC_SHA1_Update to the
appropriate type.

-Joe

Two questions:

1. Is this an already reported bug? If so, would you happen to know what
it is so I can track it for resolution (to remove the work-around when
it is resolved)?

I made the protocol def this:
var bar: (UnsafeMutablePointer<Context>?, UnsafeRawPointer?, CC_LONG) ->
Int32 { get }

Then the imp this:
let bar = unsafeBitCast(CC_SHA1_Update, to:
((UnsafeMutablePointer<CC_SHA1_CTX>?, UnsafeRawPointer?, CC_LONG) ->
Int32).self)

I don't believe we have a bug for this issue yet. The intent for IUO in Swift 3 is that it acts only as a modifier for declarations; as parts of types, it's equivalent to Optional. A function reference like CC_SHA1_Update should formally have Optional typed parameters.

2. Perhaps I'm doing something wrong here but I feel like this just make
the code less safe. It seems now I can send in an optional, read: nil,
pointer to this `bar` method. On face, this seems dangerous. The
`CC_SHA1_Update` method seems explicit in that it will not deal with
`nil`. So it seems that this thing is now reporting a safer API than
what is actually there. Or did I misunderstand? Should I be dropping the
IUO all together and just make it `UnsafeMutablePointer<Context>` and
`UnsafeRawPointer`?

We imported the function as IUO because we don't have any information one way or the other from the original C code about whether it takes nil or not. It's up to you not to pass in 'nil' if it doesn't accept 'nil'.

-Joe

···

On Oct 24, 2016, at 3:09 PM, Ryan Lovelett <swift-dev@ryan.lovelett.me> wrote: