Proposal: Improve Import of Scanner APIs into Swift 3

Working on a function for Foundation’s Scanner I stumbled on this LLVM crash: [SR-3295] LLVM Crash using AutoreleasingUnsafeMutablePointer<Bool?>? · Issue #45883 · apple/swift · GitHub

This got me thinking about a workaround and I would like to prose this:

When importing Foundation into Swift 3, all

AutoreleasingUnsafeMutablePointer<T?>?

should instead be exposed as simple:

inout T?

e.g.

open func scanString(_ string: String, into result: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool

would become

open func scanString(_ string: String, into result: inout String?) -> Bool

The call would stay exactly the same for normal use cases where you specify a receiving variable:

var string: String?
scanString("=", into: &string)

because inout parameters require a &

for the use case where you don’t require a receiving parameter, a second method without result parameter would be generated:

open func scanString(_ string: String) -> Bool

This is necessary because you cannot specify nil or an immutable value for an inout parameter.

A fixit/migration would change calls to

scanString(“foo", into result: nil)

into

scanString(“foo")

The normal call with receiving variable would stay the same. But the case without return would become more concise.

What do you think?

kind regards
Oliver Drobnik

<https://github.com/apple/swift-corelibs-foundation/blob/5f8656628c79bf4df3980efbf45dfb3eebd35766/Foundation/NSScanner.swift#L485-L487&gt;

  /// Revised API for avoiding usage of AutoreleasingUnsafeMutablePointer and better Optional usage.
  /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative
  /// - Note: Since this API is under consideration it may be either removed or revised in the near future
  extension Scanner {
      public func scanInt() -> Int32?
      public func scanInteger() -> Int?
      public func scanLongLong() -> Int64?
      public func scanUnsignedLongLong() -> UInt64?
      public func scanFloat() -> Float?
      public func scanDouble() -> Double?
      public func scanHexInt() -> UInt32?
      public func scanHexLongLong() -> UInt64?
      public func scanHexFloat() -> Float?
      public func scanHexDouble() -> Double?
      public func scanString(string searchString: String) -> String?
      public func scanCharactersFromSet(_ set: CharacterSet) -> String?
      public func scanUpToString(_ string: String) -> String?
      public func scanUpToCharactersFromSet(_ set: CharacterSet) -> String?
  }

Foundation issues should be discussed on the swift-corelibs-dev list.

-- Ben

···

On 30 Nov 2016, at 10:10, Oliver Drobnik via swift-evolution <swift-evolution@swift.org> wrote:

Working on a function for Foundation’s Scanner I stumbled on this LLVM crash: [SR-3295] LLVM Crash using AutoreleasingUnsafeMutablePointer<Bool?>? · Issue #45883 · apple/swift · GitHub

This got me thinking about a workaround and I would like to prose this:

When importing Foundation into Swift 3, all

AutoreleasingUnsafeMutablePointer<T?>?

should instead be exposed as simple:

inout T?

e.g.

open func scanString(_ string: String, into result: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool

would become

open func scanString(_ string: String, into result: inout String?) -> Bool

The call would stay exactly the same for normal use cases where you specify a receiving variable:

var string: String?
scanString("=", into: &string)

because inout parameters require a &

for the use case where you don’t require a receiving parameter, a second method without result parameter would be generated:

open func scanString(_ string: String) -> Bool

This is necessary because you cannot specify nil or an immutable value for an inout parameter.

A fixit/migration would change calls to

scanString(“foo", into result: nil)

into

scanString(“foo")

The normal call with receiving variable would stay the same. But the case without return would become more concise.

What do you think?

kind regards
Oliver Drobnik