Can't initialise using a UTF8 string from within 'withUnsafeBufferPointer' expression


(Karl) #1

As I understand it, we are supposed to use withUnsafe{Mutable/Buffer}Pointer or withExtendedLifetime to guarantee that objects we take pointers of will exist and won’t be optimised out by the compiler.

However, this leads to a problem when trying to initialise something which expects a UTF8 string using only the standard library (not Foundation’s equivalent cStringUsingEncoding):

extension DispatchIO {

  convenience init(type: DispatchIO.StreamType, path: String, oflag: Int32, mode: mode_t, queue: DispatchQueue, cleanupHandler: (error: Int32) -> Void) {

    let utf8Path = path.nulTerminatedUTF8
    utf8Path.withUnsafeBufferPointer {
      self.init(type: type, path: UnsafePointer($0.baseAddress!), oflag: oflag, mode: mode, queue: queue, cleanupHandler: cleanupHandler)
    }
  }
}

ERROR: Initializer delegation ('self.init') cannot be nested in another expression

I don’t really understand why that isn’t allowed for a non-capturing closure, but if we accept that, how do I actually use those pointer/extended lifetime functions to initialise things?

Thanks

Karl


(Martin R) #2

This is not an answer to your question, but note that you can pass a Swift String to functions expecting an UnsafePointer<Int8> (C String) parameter, and the compiler will generate a temporary NUL-terminated UTF-8 representation for you:

  let io = DispatchIO(type: .stream, path: "/path/to/file", ...)

So you don't need a convenience initializer for _this_ purpose.

···

On 18 Jul 2016, at 07:17, Karl via swift-users <swift-users@swift.org> wrote:

As I understand it, we are supposed to use withUnsafe{Mutable/Buffer}Pointer or withExtendedLifetime to guarantee that objects we take pointers of will exist and won’t be optimised out by the compiler.

However, this leads to a problem when trying to initialise something which expects a UTF8 string using only the standard library (not Foundation’s equivalent cStringUsingEncoding):

extension DispatchIO {

  convenience init(type: DispatchIO.StreamType, path: String, oflag: Int32, mode: mode_t, queue: DispatchQueue, cleanupHandler: (error: Int32) -> Void) {

    let utf8Path = path.nulTerminatedUTF8
    utf8Path.withUnsafeBufferPointer {
      self.init(type: type, path: UnsafePointer($0.baseAddress!), oflag: oflag, mode: mode, queue: queue, cleanupHandler: cleanupHandler)
    }
  }
}

ERROR: Initializer delegation ('self.init') cannot be nested in another expression

I don’t really understand why that isn’t allowed for a non-capturing closure, but if we accept that, how do I actually use those pointer/extended lifetime functions to initialise things?

Thanks

Karl

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Karl) #3

Oh, my…

Isn’t it kind of strange that we have such a hidden implicit conversion, yet we don’t have implicit widening conversions?

Also, as interesting as that may be, I’m also curious what to do in the general case for types without magic compiler optimisations.

Karl

···

On 18 Jul 2016, at 14:51, Martin R <martinr448@gmail.com> wrote:

This is not an answer to your question, but note that you can pass a Swift String to functions expecting an UnsafePointer<Int8> (C String) parameter, and the compiler will generate a temporary NUL-terminated UTF-8 representation for you:

let io = DispatchIO(type: .stream, path: "/path/to/file", ...)

So you don't need a convenience initializer for _this_ purpose.


(Brent Royal-Gordon) #4

Wait for Swift 4, apparently: https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md#rationale

Or use a class method, or two-phase initialization, or some other trick to get around this limitation.

···

On Jul 18, 2016, at 11:44 AM, Karl via swift-users <swift-users@swift.org> wrote:

Also, as interesting as that may be, I’m also curious what to do in the general case for types without magic compiler optimisations.

--
Brent Royal-Gordon
Architechies