Swift 3 - CharacterSet.isSuperset Crashes

I'm running XCode 8.0 (8A218a), and just migrated my code to Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38). Now, I'm getting an EXC_BAD_ACCESS on this line (hard-coded strings for illustration):

CharacterSet(charactersIn: ".0123456789").isSuperset(of: CharacterSet(charactersIn: "1"))

Here's the full trace:

* thread #1: tid = 0x1726389, 0x000000011497d833 CoreFoundation`__CFCharacterSetEqual + 611, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100000794)
    frame #0: 0x000000011497d833 CoreFoundation`__CFCharacterSetEqual + 611
    frame #1: 0x00000001149962fb CoreFoundation`CFCharacterSetIsSupersetOfSet + 1531
    frame #2: 0x0000000114995cec CoreFoundation`-[__NSCFCharacterSet isSupersetOfSet:] + 12
    frame #3: 0x0000000115a401dc libswiftFoundation.dylib`function signature specialization <Arg[0] = Owned To Guaranteed> of Foundation.CharacterSet.isSuperset (of : Foundation.CharacterSet) -> Swift.Bool + 44
    frame #4: 0x00000001159df81f libswiftFoundation.dylib`Foundation.CharacterSet.isSuperset (of : Foundation.CharacterSet) -> Swift.Bool + 15
  * frame #5: 0x000000010ea21fcd My App`InputViewController.textField(textField=0x00007f8b0f410f20, range=location=0, length=0, string="4", self=0x00007f8b0f64cac0) -> Bool + 205 at InputViewController.swift:159
    frame #6: 0x000000010ea2298e My App`@objc InputViewController.textField(UITextField, shouldChangeCharactersIn : _NSRange, replacementString : String) -> Bool + 126 at InputViewController.swift:0
    frame #7: 0x0000000112bf1089 UIKit`-[UITextField keyboardInput:shouldInsertText:isMarkedText:] + 318
    frame #8: 0x0000000112391a20 UIKit`-[UIKeyboardImpl callShouldInsertText:] + 110
    frame #9: 0x000000011239dc5d UIKit`-[UIKeyboardImpl addInputEvent:executionContext:] + 965
    frame #10: 0x000000011239d827 UIKit`__81-[UIKeyboardImpl addInputString:withFlags:withInputManagerHint:executionContext:]_block_invoke + 55
    frame #11: 0x0000000112c20b04 UIKit`-[UIKeyboardTaskExecutionContext returnExecutionToParentWithInfo:] + 278
    frame #12: 0x000000011239d766 UIKit`-[UIKeyboardImpl addInputString:withFlags:withInputManagerHint:executionContext:] + 433
    frame #13: 0x00000001123aeb90 UIKit`-[UIKeyboardImpl handleKeyWithString:forKeyEvent:executionContext:] + 733
    frame #14: 0x00000001123ae631 UIKit`-[UIKeyboardImpl handleKeyEvent:executionContext:] + 1744
    frame #15: 0x00000001123add55 UIKit`-[UIKeyboardImpl _handleKeyEvent:executionContext:] + 217
    frame #16: 0x00000001125dfa94 UIKit`-[UIKeyboardLayoutStar completeRetestForTouchUp:timestamp:interval:executionContext:] + 5037
    frame #17: 0x00000001123bfa19 UIKit`__45-[UIKeyboardLayout touchUpTaskForTouchState:]_block_invoke + 233
    frame #18: 0x0000000112c21148 UIKit`-[UIKeyboardTaskQueue continueExecutionOnMainThread] + 385
    frame #19: 0x00000001123bf6f3 UIKit`-[UIKeyboardLayout _touchEndedProcessingForTouches:] + 342
    frame #20: 0x000000011213d0d5 UIKit`-[UIWindow _sendTouchesForEvent:] + 2747
    frame #21: 0x000000011213e7c3 UIKit`-[UIWindow sendEvent:] + 4011
    frame #22: 0x00000001120eba33 UIKit`-[UIApplication sendEvent:] + 371
    frame #23: 0x00000001128ddb6d UIKit`__dispatchPreprocessedEventFromEventQueue + 3248
    frame #24: 0x00000001128d6817 UIKit`__handleEventQueue + 4879
    frame #25: 0x0000000114956311 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    frame #26: 0x000000011493b59c CoreFoundation`__CFRunLoopDoSources0 + 556
    frame #27: 0x000000011493aa86 CoreFoundation`__CFRunLoopRun + 918
    frame #28: 0x000000011493a494 CoreFoundation`CFRunLoopRunSpecific + 420
    frame #29: 0x0000000117a8ea6f GraphicsServices`GSEventRunModal + 161
    frame #30: 0x00000001120cdf34 UIKit`UIApplicationMain + 159
    frame #31: 0x000000010e9ca37f My App`main(argc=1, argv=0x00007fff512a0660) + 111 at main.m:14
    frame #32: 0x0000000115dd068d libdyld.dylib`start + 1

I found https://bugs.swift.org/browse/SR-2307, but it seems like this might be a different issue. Any ideas?

I could have confirmed that your simple code crashed randomly (execution context might affect). You'd better include a repeated case to send a bug report.

And even when it did not crash, had never generated the right result.


for ch in ".0123456789".unicodeScalars {
    let str = String(ch)
    print(str, CharacterSet(charactersIn: ".0123456789").isSuperset(of: CharacterSet(charactersIn: str)))
}

Sample output:

. false
Program ended with exit code: 9 //<- crashed at str == "0", so, teminated manually.


Seems the current bridging of `CharacterSet` generates something weird which does not work with `isSuperset(of:)`.

(It internally calls `CFCharacterSetIsSupersetOfSet(_:_:)`.)


Until this issue is fixed, you may need to avoid using `isSuperset(of:)`.


This code:

str.rangeOfCharacter(from: CharacterSet(charactersIn: ".0123456789").inverted) == nil

will generate the same result as the expected result of this:

CharacterSet(charactersIn: ".0123456789").isSuperset(of: CharacterSet(charactersIn: str))


(Creating a `CharacterSet` may consume some heap and time, better keep `CharacterSet(charactersIn: ".0123456789").inverted` in a constant property.)

Swift 3 - CharacterSet.isSuperset Crashes
 
 
Q