You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.0.0
Additional Detail from JIRA
Votes
0
Component/s
Foundation
Labels
Bug
Assignee
None
Priority
Medium
md5: b147999c754ecf7fa2144e4177e48659
relates to:
SR-3006 CharacterSet should have a way of ensuring the wrapped NSCharacterSet is immutable
Issue Description:
After mutating a CharacterSet it's backed internally by an NSMutableCharacterSet. In this case, it turns out that bridging to Obj-C just returns the backing NSMutableCharacterSet without copying it, and so mutations to this returned NSMutableCharacterSet actually mutate the original CharacterSet.
importFoundationvarcs = CharacterSet(charactersIn: "foo")
cs.insert(charactersIn: "bar")
(csas! NSMutableCharacterSet).addCharacters(in: "x")
print(cs.contains("x")) // should be false, prints true
Unfortunately, fixing this will have performance implications on any code that has to bridge it to Obj-C, especially if it does so repeatedly.
The text was updated successfully, but these errors were encountered:
I think the ideal solution here would be, if the character set is mutable, to have the act of bridging actually replace the inner storage with the copied immutable NSCharacterSet, as bridged character sets are unlikely to be subsequently mutated and mutable character sets have a performance penalty (see SR-3006). But Swift has no precedent for a bridging operation actually mutating the source value.
Barring that, it might be worth actually considering the idea of changing CharacterSet to be immutable and to have a separate type as a mutable character set. This way CharacterSet can be guaranteed to be backed by an NSCharacterSet, and the separate type can be non-bridgeable and thus sidestep the issue of exposing its NSMutableCharacterSet. This separate type could be something like a CharacterSetBuilder that uses a builder pattern API to construct a CharacterSet (the idea being that character sets are generally not mutated after they're constructed, any such changes after the fact are usually done with the immutable methods that return new character sets). For backwards compatibility reasons we can keep the mutating methods on CharacterSet but deprecate them, and then fix CharacterSet's Obj-C bridging to copy the inner NSMutableCharacterSet if mutable. And finally, we can ensure that all non-deprecated CharacterSet methods result in having an immutable NSCharacterSet as the backing storage (such as the methods that return a brand new character set; I haven't checked what they do today, but hopefully the backing storage for the returned character set is already immutable).
I'm not aware of any precedent for the Swift stdlib / SDK overlay to provide a builder pattern like this, but this approach very neatly ensures that anyone constructing a CharacterSet will end up with an immutable backing storage, which is important for performance reasons.
Environment
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.0.0
Additional Detail from JIRA
md5: b147999c754ecf7fa2144e4177e48659
relates to:
Issue Description:
After mutating a
CharacterSet
it's backed internally by anNSMutableCharacterSet
. In this case, it turns out that bridging to Obj-C just returns the backingNSMutableCharacterSet
without copying it, and so mutations to this returnedNSMutableCharacterSet
actually mutate the originalCharacterSet
.Unfortunately, fixing this will have performance implications on any code that has to bridge it to Obj-C, especially if it does so repeatedly.
The text was updated successfully, but these errors were encountered: