Open bobergj opened 5 years ago
@milseman sorry for using bandwidth but what do you think?
It looks like you're using indices derived from one string in another, which is not safe (and we probably want to find a way to trap on it in the future). Is there a way we could make doing the right thing more ergonomic here?
It looks like you're using indices derived from one string in another
Technically that is true, because we have another string instance (with a different storage) after bridging back and forth. But the fact that NLTagger is implemented in Objective-C could be considered an implementation detail.
Another example which is perhaps more to the point:
let str = "同意"
let range = str.startIndex..<str.index(after: str.startIndex)
print(str[range]) // "同" OK
var str1 = str
print(str1[range]) // "同" OK and arguably safe, we have not mutated the string
str1.append("foo")
print(str1[range]) // "同" OK and arguably safe. Collection append (in contrast to other methods) is not documented to invalidate indices
class SomeSwiftClass {
var str: String = ""
}
let someSwiftClass = SomeSwiftClass()
someSwiftClass.str = str
let str2 = someSwiftClass.str
print(str2[range]) // "同" OK and arguably safe, we have not mutated the string
let someObjcClass = SomeObjcClass() // Objc class with @property (nonatomic, strong) NSString *string;
someObjcClass.str = str
let str3 = someObjcClass.str
print(str3[range]) // BOOM Fatal error: String index range is out of bounds
Attachment: Download
Environment
Swift 5, Swift 5.1 Xcode Version 10.3 (10G8), Xcode Version 11.0 beta 4 (11M374r) macOS 10.14.5 (18F132)Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 1 | |Component/s | Foundation | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 059d4512ad3a2419b0bb7d656dc0731arelates to:
Issue Description:
How this can bite you in practice:
The aboves does nothing in Swift 5.0, prints "同意" in Swift 4.2.
I understand that the above code may never have been valid in Swift, but this bridging behaviour makes it slightly unergonomic to work with several Apple frameworks APIs.
Alternatively, perhaps a function similar to "equivalentRange" below should be included in Swift Foundation?
Workaround: