Swift: String(format:_:) with positional specifiers causes exception in Xcode playground

Originator:rsfinn
Number:rdar://26051182 Date Originated:5/2/2016
Status:Closed Resolved:Fixed
Product:Xcode Product Version:7.3
Classification:Serious Bug Reproducible:Always
 
Summary:
The documentation for the String struct in the Swift Standard Library Reference states that "String is bridged to Objective-C as NSString", which implies that the Swift convenience initializer String(format:_:) should behave the same as the Objective-C initializer -[NSString initWithFormat:...].  However, the behavior actually differs when the format string contains positional specifiers such as "%1$@" (which the String Programming Guide documents as supported by NSString in the section "String Format Specifiers").

Specifically, when running in an Xcode playground, the use of a positional specifier in the format string causes an EXC_BAD_INSTRUCTION exception.  

(When running equivalent code on the command line, the initializer returns a String object that represents a tuple containing the unprocessed format string and the argument(s) that would have been applied.  This bug is being reported separately to the Swift project.)

Steps to Reproduce:
In Xcode 7.3, create a playground with the following program:

import Foundation

let fmtstr = "%1$@ shall be the number thou shalt count, and the number of the counting shall be %1$@."
let stext = String(format: fmtstr, "THREE")
let nstext = NSString(format:fmtstr, "THREE")


Expected Results:
The variables stext and nstext should contain the same text, namely:

"THREE shall be the number thou shalt count, and the number of the counting shall be THREE."

Actual Results:
The line defining stext fails with an EXC_BAD_INSTRUCTION error.

Version:
Xcode Version 7.3.1 (7D1012)
(also reproducible in Xcode Version 7.3)

OS X Version 10.11.4 (15E65)

Notes:
As suggested by the program description, invoking the NSString initializer directly works around the problem on OS X when the Foundation framework is available; but this workaround is presumably not portable to Linux.

Comments

Addressed in Swift 3 / Xcode 8

This issue was addressed by a change in Swift 3.0 that removed the erroneous argument checking code that led to the crash; as a result, the submitted program no longer crashes in the playground in Xcode 8. (It is necessary to change the last line to read let nstext = NSString(format: fmtstr as NSString, "THREE") in order to avoid a Swift 3 compiler error.)


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!